import { AccountID , Address } from './account.js' ; import NEAR , { NEARTransaction } from './near.js' ; import { None , Option , Some , U64 , U256 } from './prelude.js' ; import { SubmitResult } from './schema.js' ; import { base58ToBytes , base58ToHex , bytesToHex , hexToBytes , intToHex , } from './utils.js' ; import { parse as parseRawTransaction } from '@ethersproject/transactions' ; interface NEARFunctionCall { method_name : string ; args : string ; gas : number | string ; deposit : number | string ; } interface NEARAction { FunctionCall ? : NEARFunctionCall ; } export class TransactionID { protected constructor ( public readonly id ) { } static zero ( ) { return new TransactionID ( `0x${ '00' . repeat ( 32 ) }` ) ; } static fromHex ( id ) { return new TransactionID ( id ) ; } static fromBase58 ( id ) { return new TransactionID ( base58ToHex ( id ) ) ; } toString ( ) { return this . id ; } } const evmMethods = [ 'raw_call' , 'submit' ] ; export class Transaction { constructor ( public readonly nonce , public readonly gasPrice , public readonly gasLimit , public readonly to , public readonly value , public readonly data , public readonly v ? , public readonly r ? , public readonly s ? , public readonly from ? , public readonly hash ? , public readonly result ? , public readonly near ? ) { } static fromOutcome ( outcome , contractID ? ) { const contractID_ = contractID || AccountID . aurora ( ) ; if ( outcome . transaction . receiver_id != contractID_ . id ) { return None ; } const actions = outcome . transaction . actions as NEARAction [ ] ; const action = actions . find ( ( action ) => action . FunctionCall && evmMethods . includes ( action . FunctionCall . method_name ) ) ; if ( ! action ) { return None ; } switch ( action . FunctionCall ?. method_name ) { case 'raw_call' : case 'submit' : return this . fromSubmitCall ( outcome , action . FunctionCall ) ; default : return None ; } } static fromSubmitCall ( outcome , functionCall ) { try { const outcomeStatus = outcome . status as any ; if ( outcomeStatus . Failure ) { console . error ( 'Failure outcome:' , outcomeStatus . Failure ) ; return None ; } const outcomeBuffer = Buffer . from ( outcomeStatus . SuccessValue , 'base64' ) ; const transaction = parseRawTransaction ( Buffer . from ( functionCall . args , 'base64' ) ) ; const receiptIDs = outcome . transaction_outcome ?. outcome ?. receipt_ids ; const executionResult = SubmitResult . decode ( outcomeBuffer ) ; return Some ( new Transaction ( transaction . nonce , BigInt ( transaction . gasPrice . toString ( ) ) , BigInt ( transaction . gasLimit . toString ( ) ) , Address . parse ( transaction . to ) . ok ( ) , BigInt ( transaction . value . toString ( ) ) , hexToBytes ( transaction . data ) , BigInt ( transaction . v ) , BigInt ( transaction . r ) , BigInt ( transaction . s ) , transaction . from ? Address . parse ( transaction . from ) . unwrap ( ) : undefined , transaction . hash , executionResult , { hash : base58ToBytes ( outcome . transaction_outcome . id ) , receiptHash : Array . isArray ( receiptIDs ) && receiptIDs ?. length ? base58ToBytes ( receiptIDs [ 0 ] ! ) : undefined , } ) ) ; } catch ( error ) { console . error ( error ) ; return None ; } } isSigned ( ) { return this . v !== undefined && this . r !== undefined && this . s !== undefined ; } toJSON ( ) { return { nonce : intToHex ( this . nonce ) , gasPrice : intToHex ( this . gasPrice ) , gas : intToHex ( this . gasLimit ) , to : this . to . isSome ( ) ? this . to . unwrap ( ) . toString ( ) : null , value : intToHex ( this . value ) , input : bytesToHex ( this . data ) , v : this . v !== undefined ? intToHex ( this . v ) : undefined , r : this . r !== undefined ? intToHex ( this . r ) : undefined , s : this . s !== undefined ? intToHex ( this . s ) : undefined , from : this . from ? this . from . toString ( ) : undefined , hash : this . hash , } ; } }