Use cases

Three scenarios in which analysis offers insights.

A wallet developer, a security auditor, and a DeFi engineer look at the same Sui or Aptos transaction. Each asks a different question. Kinetics answers all three from the transaction's structure alone — statically, client-side, before anything is signed or sent.

Pick a role below. Every finding shown is the analyzer's real output on a representative transaction; addresses and amounts are illustrative.

In practice
APTOS

What is my user actually approving?

wallet developer · signing preview
Situation

A dApp hands your wallet an Aptos transaction and a friendly label: "claim rewards". The confirmation screen you build is the last thing the user sees before their APT can move. You want it to say, in plain words, exactly what this payload does — not what the dApp calls it.

What you do

Before you render the prompt, run the payload through the Move analyzer. It decodes the entry function, its type argument, and its arguments — no execution, no signature.

import @choosek/kinetics → call analyzeMoveTransaction(payload)
What Kinetics shows
signerdestination − 50 APT signer · 0x4e…c1 0x9f2c… unknown
function 0x1::aptos_account::transfer_coins
type arg 0x1::aptos_coin::AptosCoin  ·  args [ 0x9f2c…e70a, 50 APT ]
!This is a value-out transfer. 50 APT leaves the signer to 0x9f2c…. Whatever the calling UI named it, the payload's own content is a plain coin transfer — surface that before the tap.
effect transfer out asset APT amount 50 payload entry fn
signer value leaving account decoded from the payload — no signing
Your user sees “Send 50 APT to 0x9f2c…” and not just "confirm". The decode is the transaction's own content — the wallet just makes it legible in the half-second before a signature commits it.
SUI

Does it send value only where it claims?

security auditor · integrator due-diligence
Situation

You're reviewing an unfamiliar transaction before trusting it: it unwinds a liquidity position, swaps one side, consolidates the proceeds, and sends them to an address. You need to confirm the money lands where it should and that nothing unexpected is created or destroyed.

What you do

Paste the digest. Read the value flow into every sink and the object accounting, instead of tracing four commands and their result handles by hand.

go to kinetics.network → paste digest → analyze
What Kinetics shows
inputscommandssink LP token pool remove swap merge → addr
Taint into the transfer sink: reached only by LP token, pool, and the destination address. No stray input feeds the payout.
Objects balance. 1 created, 1 deleted (the LP burned), 2 mutated — net object delta 0.
taint → transfer {LP, pool, addr} net objects 0 gas net 0.00107 SUI
input taint path critical path transfer sink
In one read you've confirmed the proceeds go to exactly that address — nothing else reaches the transfer — and that the object accounting closes. The same check against a raw command list is slow and easy to get wrong.
SUI

Will it land — or strand a coin?

DeFi engineer · pre-submit debugging
Situation

You're shipping a one-click zap: take the user's SUI, swap part of it to USDC, add both sides to a pool, send the LP token back. Your happy-path test is green — but a teammate's transaction aborts on-chain with unused value without drop, and the error doesn't say which value.

What you do

Paste the transaction — a digest, or the PTB your SDK just built, before you ever submit it.

go to kinetics.network → paste digest or PTB JSON → analyze
What Kinetics shows
incommandsout amounts Split swap add_liq LP coin · unused
!Dangling result at command 0 — split output never consumed. The LP-side coin has no outgoing edge, so the transaction aborts.
dependency depth 4 · serial dangling 1 package 0xdex
input critical path output dropped / dangling
See it as a failing CI testthe same finding, asserted in your test suitekinetics.test.ts
import { describe, it, expect } from "vitest";
import { analyzePtb } from "@choosek/kinetics";
import { buildZapPtb } from "../src/zap";

describe("zap → LP", () => {
  const ptb = buildZapPtb({
    amountToSwap: 1_000_000n,
    amountForLp:  1_000_000n,
    pool: POOL_ID,
    recipient: USER,
  });

  it("strands no value", () => {
    const { resources } = analyzePtb(ptb);
    // A dangling result is a coin nothing consumes — on Sui that
    // aborts the whole transaction with "unused value without drop".
    expect(resources.dangling).toHaveLength(0);
  });

  it("pays only the recipient", () => {
    const { taint } = analyzePtb(ptb);
    const transfer = taint.sinks.find((s) => s.kind === "transfer");
    // input 3 is the recipient address; nothing else should reach it.
    expect(transfer?.taintedBy).toContain(3);
  });
});
Run against the buggy zap, the first test fails with the exact location: dangling → [{ command: 0, reason: "split output never consumed" }]. Wire the stranded coin into add_liquidity and it goes green — the abort is caught in CI, before any gas is spent.
Fix it — thread the stranded coin into add_liquidity — and re-run: dangling results: 0. You found a submit-time abort from the transaction's shape, before spending a cent of gas, and without decoding a single result handle.
Your transaction is the best example.

Paste a Sui or Aptos digest — or the PTB your SDK just built — and read its structure before you sign or send.

Open the analyzer →