@indexing/jiti 0.1.5 → 0.1.7

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/main.js CHANGED
@@ -1467,6 +1467,23 @@ const $2e46ec862e47c14f$export$400f08bfae9ee97f = {
1467
1467
  if (!Array.isArray(typedBlock.transactions)) return [];
1468
1468
  for (const typedTx of typedBlock.transactions || []){
1469
1469
  if (typedTx.TransactionType !== "Payment") continue;
1470
+ // Failed XRPL payments still burn Fee. Emit a fee-only transfer (to: null) so
1471
+ // callers account for the gas, and skip the payment amount that never landed.
1472
+ if (typedTx.metaData?.TransactionResult && typedTx.metaData.TransactionResult !== "tesSUCCESS") {
1473
+ transfers.push({
1474
+ amount: BigInt(typedTx.Fee ?? "0"),
1475
+ blockNumber: parseInt(typedBlock.ledger_index, 10),
1476
+ from: typedTx.Account ?? "UNKNOWN",
1477
+ memo: typedTx.DestinationTag,
1478
+ timestamp: typedBlock.close_time_iso || null,
1479
+ to: null,
1480
+ token: "XRP",
1481
+ tokenType: "NATIVE",
1482
+ transactionGasFee: BigInt(typedTx.Fee ?? "0"),
1483
+ transactionHash: typedTx.hash ?? ""
1484
+ });
1485
+ continue;
1486
+ }
1470
1487
  const deliveredOrAmount = typedTx.metaData?.delivered_amount ?? typedTx.Amount ?? "0";
1471
1488
  let tokenSymbol = "XRP";
1472
1489
  let tokenType = "NATIVE";
@@ -1515,6 +1532,45 @@ const $2e46ec862e47c14f$export$400f08bfae9ee97f = {
1515
1532
  transactionHash: "B32A6A5455777283212407FBD8CCA701505C654E5F4ADFFBE9D4D22F00889D87"
1516
1533
  }
1517
1534
  ]
1535
+ },
1536
+ // Failed XRPL payments emit ONLY a fee transfer (to: null) — the payment Amount
1537
+ // never reached the Destination, but the Fee was still burned.
1538
+ {
1539
+ params: {
1540
+ network: "RIPPLE"
1541
+ },
1542
+ payload: {
1543
+ _network: "RIPPLE",
1544
+ ledger_index: "100000000",
1545
+ close_time_iso: "2026-04-04T08:02:44Z",
1546
+ transactions: [
1547
+ {
1548
+ TransactionType: "Payment",
1549
+ Account: "rFAILFROMxxxxxxxxxxxxxxxxxxxxxxxxx",
1550
+ Destination: "rFAILTOxxxxxxxxxxxxxxxxxxxxxxxxxx",
1551
+ Amount: "1000000",
1552
+ Fee: "10",
1553
+ hash: "FAILEDXRPLTXHASH",
1554
+ metaData: {
1555
+ TransactionResult: "tecPATH_DRY"
1556
+ }
1557
+ }
1558
+ ]
1559
+ },
1560
+ output: [
1561
+ {
1562
+ amount: 10n,
1563
+ blockNumber: 100000000,
1564
+ from: "rFAILFROMxxxxxxxxxxxxxxxxxxxxxxxxx",
1565
+ memo: undefined,
1566
+ timestamp: "2026-04-04T08:02:44Z",
1567
+ to: null,
1568
+ token: "XRP",
1569
+ tokenType: "NATIVE",
1570
+ transactionGasFee: 10n,
1571
+ transactionHash: "FAILEDXRPLTXHASH"
1572
+ }
1573
+ ]
1518
1574
  }
1519
1575
  ]
1520
1576
  };
@@ -3245,58 +3301,274 @@ const $fc745f3cb8eb3f52$export$36783fc9701281c6 = {
3245
3301
 
3246
3302
 
3247
3303
 
3304
+ // Stellar amounts are stringified decimals with 7 fractional digits ("12.3456789"),
3305
+ // but jiti expresses everything in stroops (smallest unit). Stripping the dot is
3306
+ // equivalent to multiplying by 10^7.
3307
+ const $3478cd776d185339$var$toStroops = (s)=>BigInt(s.replace(".", ""));
3308
+ const $3478cd776d185339$var$effectAsset = (e)=>{
3309
+ if (e.asset_type === "native") return {
3310
+ token: null,
3311
+ tokenType: "NATIVE"
3312
+ };
3313
+ if (e.asset_issuer) return {
3314
+ token: e.asset_issuer,
3315
+ tokenType: "TOKEN"
3316
+ };
3317
+ // contract_* effects expose `asset` as a single string ("CODE:ISSUER" or "native").
3318
+ if (e.asset && e.asset !== "native") {
3319
+ const [, issuer] = e.asset.split(":");
3320
+ return {
3321
+ token: issuer ?? e.asset,
3322
+ tokenType: "TOKEN"
3323
+ };
3324
+ }
3325
+ return {
3326
+ token: null,
3327
+ tokenType: "NATIVE"
3328
+ };
3329
+ };
3330
+ const $3478cd776d185339$var$sameAsset = (a, b)=>a.asset_type === b.asset_type && a.asset_code === b.asset_code && a.asset_issuer === b.asset_issuer && a.asset === b.asset;
3331
+ // Pair account_debited/account_credited effects within a single op into transfers.
3332
+ // Used for ops where amount/asset isn't reliably on the op body (offer fills,
3333
+ // account_merge, claim_claimable_balance, liquidity_pool_*, invoke_host_function).
3334
+ // Unpaired sides become one-sided transfers (e.g. claim_claimable_balance has no
3335
+ // debit because the source is a protocol-managed escrow).
3336
+ function $3478cd776d185339$var$effectsToTransfers(typedTx, op, typedBlock) {
3337
+ const transfers = [];
3338
+ const effects = (op.effects || []).filter((e)=>typeof e.amount === "string");
3339
+ const debits = effects.filter((e)=>e.type === "account_debited" || e.type === "contract_debited");
3340
+ const credits = effects.filter((e)=>e.type === "account_credited" || e.type === "contract_credited");
3341
+ const baseFields = {
3342
+ blockNumber: typedBlock.sequence,
3343
+ memo: typedTx.memo,
3344
+ timestamp: typedTx.created_at,
3345
+ transactionGasFee: BigInt(typedTx.fee_charged),
3346
+ transactionHash: typedTx.hash
3347
+ };
3348
+ const usedCredit = new Set();
3349
+ for (const d of debits){
3350
+ if (!d.amount) continue;
3351
+ const idx = credits.findIndex((c, i)=>!usedCredit.has(i) && $3478cd776d185339$var$sameAsset(d, c) && c.amount === d.amount);
3352
+ const { token: token, tokenType: tokenType } = $3478cd776d185339$var$effectAsset(d);
3353
+ if (idx !== -1) {
3354
+ const c = credits[idx];
3355
+ usedCredit.add(idx);
3356
+ transfers.push({
3357
+ ...baseFields,
3358
+ amount: $3478cd776d185339$var$toStroops(d.amount),
3359
+ from: d.account || d.contract || null,
3360
+ to: c.account || c.contract || null,
3361
+ token: token,
3362
+ tokenType: tokenType
3363
+ });
3364
+ } else transfers.push({
3365
+ ...baseFields,
3366
+ amount: $3478cd776d185339$var$toStroops(d.amount),
3367
+ from: d.account || d.contract || null,
3368
+ to: null,
3369
+ token: token,
3370
+ tokenType: tokenType
3371
+ });
3372
+ }
3373
+ for(let i = 0; i < credits.length; i++){
3374
+ if (usedCredit.has(i)) continue;
3375
+ const c = credits[i];
3376
+ if (!c.amount) continue;
3377
+ const { token: token, tokenType: tokenType } = $3478cd776d185339$var$effectAsset(c);
3378
+ transfers.push({
3379
+ ...baseFields,
3380
+ amount: $3478cd776d185339$var$toStroops(c.amount),
3381
+ from: null,
3382
+ to: c.account || c.contract || null,
3383
+ token: token,
3384
+ tokenType: tokenType
3385
+ });
3386
+ }
3387
+ return transfers;
3388
+ }
3248
3389
  const $3478cd776d185339$export$681f497010b17679 = {
3249
3390
  match: (block)=>(0, $6bd2ca253e883278$export$ae001c77434c5340)(block) === "STELLAR",
3250
3391
  transform (block) {
3251
- let transfers = [];
3392
+ const transfers = [];
3252
3393
  const typedBlock = block;
3253
3394
  for (const typedTx of typedBlock.transactions || []){
3254
- for (const op of typedTx.operations)if (op.type === "payment") transfers.push({
3255
- amount: BigInt(op.amount.replace(".", "")),
3256
- blockNumber: typedBlock.sequence,
3257
- from: op.from,
3258
- memo: typedTx.memo,
3259
- timestamp: typedTx.created_at,
3260
- to: op.to,
3261
- token: op.asset_type === "native" ? null : op.asset_issuer,
3262
- tokenType: op.asset_type === "native" ? "NATIVE" : "TOKEN",
3263
- transactionGasFee: BigInt(typedTx.fee_charged),
3264
- transactionHash: typedTx.hash
3265
- });
3395
+ // Failed txs still burn fee_charged — emit a fee transfer (to: null) so callers
3396
+ // can account for the gas, but skip the ops that never actually moved funds.
3397
+ if (!typedTx.successful) {
3398
+ transfers.push({
3399
+ amount: BigInt(typedTx.fee_charged),
3400
+ blockNumber: typedBlock.sequence,
3401
+ from: typedTx.source_account,
3402
+ memo: typedTx.memo,
3403
+ timestamp: typedTx.created_at,
3404
+ to: null,
3405
+ token: null,
3406
+ tokenType: "NATIVE",
3407
+ transactionGasFee: BigInt(typedTx.fee_charged),
3408
+ transactionHash: typedTx.hash
3409
+ });
3410
+ continue;
3411
+ }
3412
+ for (const op of typedTx.operations){
3413
+ const baseFields = {
3414
+ blockNumber: typedBlock.sequence,
3415
+ memo: typedTx.memo,
3416
+ timestamp: typedTx.created_at,
3417
+ transactionGasFee: BigInt(typedTx.fee_charged),
3418
+ transactionHash: typedTx.hash
3419
+ };
3420
+ if (op.type === "payment") transfers.push({
3421
+ ...baseFields,
3422
+ amount: $3478cd776d185339$var$toStroops(op.amount),
3423
+ from: op.from,
3424
+ to: op.to,
3425
+ token: op.asset_type === "native" ? null : op.asset_issuer,
3426
+ tokenType: op.asset_type === "native" ? "NATIVE" : "TOKEN"
3427
+ });
3428
+ else if (op.type === "create_account") // create_account funds a new account with native XLM via starting_balance —
3429
+ // economically a native payment from funder → account, but a different op
3430
+ // type because it also creates the destination ledger entry.
3431
+ transfers.push({
3432
+ ...baseFields,
3433
+ amount: $3478cd776d185339$var$toStroops(op.starting_balance),
3434
+ from: op.funder,
3435
+ to: op.account,
3436
+ token: null,
3437
+ tokenType: "NATIVE"
3438
+ });
3439
+ else if (op.type === "path_payment_strict_send" || op.type === "path_payment_strict_receive") {
3440
+ // Path payments swap source_asset → asset along a DEX path. Both legs are
3441
+ // emitted as separate transfers (different assets, different amounts) so the
3442
+ // sender debit and receiver credit are both visible from op fields alone.
3443
+ transfers.push({
3444
+ ...baseFields,
3445
+ amount: $3478cd776d185339$var$toStroops(op.source_amount),
3446
+ from: op.from,
3447
+ to: op.to,
3448
+ token: op.source_asset_type === "native" ? null : op.source_asset_issuer,
3449
+ tokenType: op.source_asset_type === "native" ? "NATIVE" : "TOKEN"
3450
+ });
3451
+ transfers.push({
3452
+ ...baseFields,
3453
+ amount: $3478cd776d185339$var$toStroops(op.amount),
3454
+ from: op.from,
3455
+ to: op.to,
3456
+ token: op.asset_type === "native" ? null : op.asset_issuer,
3457
+ tokenType: op.asset_type === "native" ? "NATIVE" : "TOKEN"
3458
+ });
3459
+ } else // Everything else — manage_*_offer fills, account_merge, claim_claimable_balance,
3460
+ // liquidity_pool_*, invoke_host_function (Soroban) — surfaces fund movements
3461
+ // only via Horizon effects. Requires oscar to attach `op.effects` (#38).
3462
+ transfers.push(...$3478cd776d185339$var$effectsToTransfers(typedTx, op, typedBlock));
3463
+ }
3266
3464
  }
3267
3465
  return transfers;
3268
3466
  },
3269
3467
  tests: [
3468
+ // Single-op token payment: source wallet → dest wallet, USDC asset.
3270
3469
  {
3271
3470
  params: {
3272
3471
  network: "STELLAR",
3273
- walletAddress: "GC5HUFIKZBK5XRNOBPXR4PBR3PWR26GP5UFRKSCOOOIENYVSF3NMA23U"
3472
+ transactionHash: "e08e8dd92bde178c554146475cafdf00cef8a8874541b1bb568760b5bd33c6e6"
3274
3473
  },
3275
- payload: "https://jiti.indexing.co/networks/stellar/59592273",
3474
+ payload: "https://jiti.indexing.co/networks/stellar/62312535",
3276
3475
  output: [
3277
3476
  {
3278
- amount: 651200000n,
3279
- blockNumber: 59592273,
3280
- from: "GC5HUFIKZBK5XRNOBPXR4PBR3PWR26GP5UFRKSCOOOIENYVSF3NMA23U",
3281
- memo: "315004227",
3282
- timestamp: "2025-10-28T17:24:17Z",
3283
- to: "GABFQIK63R2NETJM7T673EAMZN4RJLLGP3OFUEJU5SZVTGWUKULZJNL6",
3477
+ amount: 100000000n,
3478
+ blockNumber: 62312535,
3479
+ from: "GAUA7XL5K54CC2DDGP77FJ2YBHRJLT36CPZDXWPM6MP7MANOGG77PNJU",
3480
+ memo: undefined,
3481
+ timestamp: "2026-04-27T16:14:30Z",
3482
+ to: "GBTPFDSY7NFLFXAXXU725NUB2CXYM57RXG4ATYWBTK7RB57DFFNIU7RH",
3284
3483
  token: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
3285
3484
  tokenType: "TOKEN",
3286
3485
  transactionGasFee: 200n,
3287
- transactionHash: "a0e5f0cbc64a13816db1d8428c4e2f849ed9ec475b80d4cbd23a8119b1b1c010"
3288
- },
3486
+ transactionHash: "e08e8dd92bde178c554146475cafdf00cef8a8874541b1bb568760b5bd33c6e6"
3487
+ }
3488
+ ]
3489
+ },
3490
+ // path_payment_strict_send swaps source_asset → asset along a DEX path. Both legs
3491
+ // are emitted as separate transfers so the sender debit and receiver credit are
3492
+ // visible. Self-swap here (source==dest) but logic handles distinct accounts the
3493
+ // same way.
3494
+ {
3495
+ params: {
3496
+ network: "STELLAR",
3497
+ transactionHash: "f036756ae1cbf61d8e43af39b24b991b59c3684fc030de42f5d8fc2c96a672eb"
3498
+ },
3499
+ payload: "https://jiti.indexing.co/networks/stellar/62312422",
3500
+ output: [
3289
3501
  {
3290
- amount: 4445100000n,
3291
- blockNumber: 59592273,
3292
- from: "GAUA7XL5K54CC2DDGP77FJ2YBHRJLT36CPZDXWPM6MP7MANOGG77PNJU",
3502
+ amount: 1000000n,
3503
+ blockNumber: 62312422,
3504
+ from: "GCY7AY7OOO2XKZUCKLOZL3MJ62DW5UNL3ISFWDEDEEJM7JFGYZEUS55Z",
3293
3505
  memo: undefined,
3294
- timestamp: "2025-10-28T17:24:17Z",
3295
- to: "GC5HUFIKZBK5XRNOBPXR4PBR3PWR26GP5UFRKSCOOOIENYVSF3NMA23U",
3296
- token: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
3506
+ timestamp: "2026-04-27T16:03:47Z",
3507
+ to: "GCY7AY7OOO2XKZUCKLOZL3MJ62DW5UNL3ISFWDEDEEJM7JFGYZEUS55Z",
3508
+ token: "GARDNV3Q7YGT4AKSDF25LT32YSCCW4EV22Y2TV3I2PU2MMXJTEDL5T55",
3297
3509
  tokenType: "TOKEN",
3298
- transactionGasFee: 300n,
3299
- transactionHash: "c554aed41145304e03c0877c9de526cdcb8a8255c9bf156ff0dec202ab12e20d"
3510
+ transactionGasFee: 200n,
3511
+ transactionHash: "f036756ae1cbf61d8e43af39b24b991b59c3684fc030de42f5d8fc2c96a672eb"
3512
+ },
3513
+ {
3514
+ amount: 1000179n,
3515
+ blockNumber: 62312422,
3516
+ from: "GCY7AY7OOO2XKZUCKLOZL3MJ62DW5UNL3ISFWDEDEEJM7JFGYZEUS55Z",
3517
+ memo: undefined,
3518
+ timestamp: "2026-04-27T16:03:47Z",
3519
+ to: "GCY7AY7OOO2XKZUCKLOZL3MJ62DW5UNL3ISFWDEDEEJM7JFGYZEUS55Z",
3520
+ token: null,
3521
+ tokenType: "NATIVE",
3522
+ transactionGasFee: 200n,
3523
+ transactionHash: "f036756ae1cbf61d8e43af39b24b991b59c3684fc030de42f5d8fc2c96a672eb"
3524
+ }
3525
+ ]
3526
+ },
3527
+ // create_account funds a new account with native XLM — emit it as a NATIVE
3528
+ // transfer (funder → account) using starting_balance.
3529
+ {
3530
+ params: {
3531
+ network: "STELLAR",
3532
+ transactionHash: "a11add92603c4cab2396804f26acfe6fb9b0f938dc7dfa9f2ed017eb75ca039a"
3533
+ },
3534
+ payload: "https://jiti.indexing.co/networks/stellar/62080113",
3535
+ output: [
3536
+ {
3537
+ amount: 344880700n,
3538
+ blockNumber: 62080113,
3539
+ from: "GDF4UGQSY6VHWN7T4XJEZ6WYJEREMZYLNYZ5CCKYVS3V3MNYIBMTB354",
3540
+ memo: undefined,
3541
+ timestamp: "2026-04-12T04:27:18Z",
3542
+ to: "GBJO6JIIPD4JEKDTKY4CKOSQZU3ETIKVWAWU56A46W72G377BGG4PS44",
3543
+ token: null,
3544
+ tokenType: "NATIVE",
3545
+ transactionGasFee: 100n,
3546
+ transactionHash: "a11add92603c4cab2396804f26acfe6fb9b0f938dc7dfa9f2ed017eb75ca039a"
3547
+ }
3548
+ ]
3549
+ },
3550
+ // Failed Stellar txs emit ONLY a fee transfer (to: null), never the failed payment
3551
+ // operations. Ledger 61961851 / tx 9024ba4b... is the Mesh incident — the source
3552
+ // tried to send 1_000_000_000 stroops to GAGLH6..., the tx reverted, and the only
3553
+ // on-chain effect was the 100-stroop fee being charged.
3554
+ {
3555
+ params: {
3556
+ network: "STELLAR",
3557
+ transactionHash: "9024ba4b558b09042cb02afd1d46eea72597891691801375acee332273c5c26d"
3558
+ },
3559
+ payload: "https://jiti.indexing.co/networks/stellar/61961851",
3560
+ output: [
3561
+ {
3562
+ amount: 100n,
3563
+ blockNumber: 61961851,
3564
+ from: "GCP7I54JXTOZ4SJG4UARWJOMJ25JQXRHSHXQWDSV4TRVRJFDG67VUEXP",
3565
+ memo: undefined,
3566
+ timestamp: "2026-04-04T08:02:44Z",
3567
+ to: null,
3568
+ token: null,
3569
+ tokenType: "NATIVE",
3570
+ transactionGasFee: 100n,
3571
+ transactionHash: "9024ba4b558b09042cb02afd1d46eea72597891691801375acee332273c5c26d"
3300
3572
  }
3301
3573
  ]
3302
3574
  }