1+ import type { SuiTransactionBlockResponse } from '@mysten/sui/client'
12import { SuiClient } from '@mysten/sui/client'
2- import { Transaction } from '@mysten/sui/transactions'
3+ import { Transaction as SuiTransaction } from '@mysten/sui/transactions'
34import type { AssetId , ChainId } from '@shapeshiftoss/caip'
45import {
56 ASSET_NAMESPACE ,
@@ -12,6 +13,7 @@ import type { HDWallet, SuiWallet } from '@shapeshiftoss/hdwallet-core'
1213import { supportsSui } from '@shapeshiftoss/hdwallet-core'
1314import type { Bip44Params , RootBip44Params } from '@shapeshiftoss/types'
1415import { KnownChainIds } from '@shapeshiftoss/types'
16+ import { TransferType , TxStatus } from '@shapeshiftoss/unchained-client'
1517
1618import type { ChainAdapter as IChainAdapter } from '../api'
1719import { ChainAdapterError , ErrorHandler } from '../error/ErrorHandler'
@@ -27,6 +29,7 @@ import type {
2729 SignAndBroadcastTransactionInput ,
2830 SignTx ,
2931 SignTxInput ,
32+ Transaction ,
3033 ValidAddressResult ,
3134} from '../types'
3235import { ChainAdapterDisplayName , ValidAddressResultType } from '../types'
@@ -244,7 +247,7 @@ export class ChainAdapter implements IChainAdapter<KnownChainIds.SuiMainnet> {
244247 const { from, accountNumber, to, value, chainSpecific } = input
245248 const { tokenId, gasBudget, gasPrice } = chainSpecific
246249
247- const tx = new Transaction ( )
250+ const tx = new SuiTransaction ( )
248251
249252 tx . setSender ( from )
250253
@@ -445,7 +448,7 @@ export class ChainAdapter implements IChainAdapter<KnownChainIds.SuiMainnet> {
445448
446449 const gasPrice = await this . client . getReferenceGasPrice ( )
447450
448- const tx = new Transaction ( )
451+ const tx = new SuiTransaction ( )
449452
450453 tx . setSender ( from )
451454
@@ -518,7 +521,102 @@ export class ChainAdapter implements IChainAdapter<KnownChainIds.SuiMainnet> {
518521 return
519522 }
520523
521- parseTx ( ) : Promise < never > {
522- throw new Error ( 'SUI transaction parsing not yet implemented' )
524+ async parseTx ( txHashOrTx : unknown , pubkey : string ) : Promise < Transaction > {
525+ try {
526+ // Fetch full transaction data if only txHash was provided
527+ const tx =
528+ typeof txHashOrTx === 'string'
529+ ? await this . client . getTransactionBlock ( {
530+ digest : txHashOrTx ,
531+ options : {
532+ showInput : true ,
533+ showEffects : true ,
534+ showBalanceChanges : true ,
535+ } ,
536+ } )
537+ : ( txHashOrTx as SuiTransactionBlockResponse )
538+
539+ const sender = tx . transaction ?. data . sender ?? ''
540+
541+ const txid = tx . digest
542+ const blockHeight = Number ( tx . checkpoint ?? 0 )
543+ const blockTime = tx . timestampMs ? Math . floor ( Number ( tx . timestampMs ) / 1000 ) : 0
544+
545+ const latestCheckpoint = await this . client . getLatestCheckpointSequenceNumber ( )
546+ const confirmations = tx . checkpoint ? Number ( latestCheckpoint ) - Number ( tx . checkpoint ) + 1 : 0
547+
548+ const status =
549+ tx . effects ?. status . status === 'success'
550+ ? TxStatus . Confirmed
551+ : tx . effects ?. status . status === 'failure'
552+ ? TxStatus . Failed
553+ : TxStatus . Unknown
554+
555+ const gasUsed = tx . effects ?. gasUsed
556+ const fee = gasUsed
557+ ? {
558+ assetId : this . assetId ,
559+ value : (
560+ BigInt ( gasUsed . computationCost ) +
561+ BigInt ( gasUsed . storageCost ) -
562+ BigInt ( gasUsed . storageRebate )
563+ ) . toString ( ) ,
564+ }
565+ : undefined
566+
567+ const balanceChanges = tx . balanceChanges ?? [ ]
568+
569+ const transfers = balanceChanges . map ( change => {
570+ let ownerAddress : string | null = null
571+ if ( typeof change . owner === 'object' && 'AddressOwner' in change . owner ) {
572+ ownerAddress = change . owner . AddressOwner
573+ }
574+
575+ const assetId =
576+ change . coinType === '0x2::sui::SUI'
577+ ? this . assetId
578+ : toAssetId ( {
579+ chainId : this . chainId ,
580+ assetNamespace : ASSET_NAMESPACE . suiCoin ,
581+ assetReference : change . coinType ,
582+ } )
583+
584+ const amount = BigInt ( change . amount )
585+ const isReceive = amount > 0n
586+ const isSend = amount < 0n
587+
588+ const transferType =
589+ ownerAddress === pubkey
590+ ? isReceive
591+ ? TransferType . Receive
592+ : TransferType . Send
593+ : TransferType . Contract
594+
595+ return {
596+ assetId,
597+ from : isSend ? [ sender ] : ownerAddress ? [ ownerAddress ] : [ sender ] ,
598+ to : isReceive ? [ ownerAddress ?? sender ] : [ sender ] ,
599+ type : transferType ,
600+ value : amount < 0n ? ( - amount ) . toString ( ) : amount . toString ( ) ,
601+ }
602+ } )
603+
604+ return {
605+ txid,
606+ blockHeight,
607+ blockTime,
608+ blockHash : undefined ,
609+ chainId : this . chainId ,
610+ confirmations,
611+ status,
612+ fee,
613+ transfers,
614+ pubkey,
615+ }
616+ } catch ( err ) {
617+ return ErrorHandler ( err , {
618+ translation : 'chainAdapters.errors.parseTx' ,
619+ } )
620+ }
523621 }
524622}
0 commit comments