1- import { BaseCoin as CoinConfig } from '@bitgo/statics' ;
2- import { BuildTransactionError , TransactionType , BaseTransaction } from '@bitgo/sdk-core' ;
1+ import { BaseCoin as CoinConfig , FlareNetwork } from '@bitgo/statics' ;
2+ import { BuildTransactionError , TransactionType , BaseTransaction , BaseKey } from '@bitgo/sdk-core' ;
33import { Credential , Signature , TransferableInput , TransferableOutput } from '@flarenetwork/flarejs' ;
4- import { TransactionExplanation , DecodedUtxoObj } from './iface' ;
4+ import { TransactionExplanation , DecodedUtxoObj , BaseAddress } from './iface' ;
5+ import { KeyPair } from './keyPair' ;
6+ import BigNumber from 'bignumber.js' ;
57import {
68 ASSET_ID_LENGTH ,
79 TRANSACTION_ID_HEX_LENGTH ,
810 PRIVATE_KEY_HEX_LENGTH ,
911 SECP256K1_SIGNATURE_LENGTH ,
1012 TRANSACTION_ID_PREFIX ,
11- DEFAULT_NETWORK_ID ,
12- EMPTY_BUFFER_SIZE ,
1313 HEX_PREFIX ,
1414 HEX_PREFIX_LENGTH ,
1515 DECIMAL_RADIX ,
1616 SIGNING_METHOD ,
1717 AMOUNT_STRING_ZERO ,
18- DEFAULT_LOCKTIME ,
19- DEFAULT_THRESHOLD ,
2018 ZERO_BIGINT ,
2119 ZERO_NUMBER ,
2220 ERROR_AMOUNT_POSITIVE ,
@@ -35,51 +33,41 @@ import {
3533 FLARE_ATOMIC_PARSED_PREFIX ,
3634 HEX_ENCODING ,
3735} from './constants' ;
38- import { createFlexibleHexRegex } from './utils' ;
36+ import utils , { createFlexibleHexRegex } from './utils' ;
37+ import { TransactionBuilder } from './transactionBuilder' ;
38+ import { Transaction } from './transaction' ;
3939
4040/**
4141 * Flare P-chain atomic transaction builder with FlareJS credential support.
4242 * This provides the foundation for building Flare P-chain transactions with proper
4343 * credential handling using FlareJS Credential and Signature classes.
4444 */
45- export abstract class AtomicTransactionBuilder {
45+ export abstract class AtomicTransactionBuilder extends TransactionBuilder {
4646 protected readonly _coinConfig : Readonly < CoinConfig > ;
4747 // External chain id (destination) for export transactions
4848 protected _externalChainId : Buffer | undefined ;
4949
5050 protected _utxos : DecodedUtxoObj [ ] = [ ] ;
51-
52- protected transaction : {
53- _network : Record < string , unknown > ;
54- _networkID : number ;
55- _blockchainID : Buffer ;
56- _assetId : Buffer ;
57- _fromAddresses : string [ ] ;
58- _to : string [ ] ;
59- _locktime : bigint ;
60- _threshold : number ;
61- _fee : { fee : string ; feeRate ?: string ; size ?: number } ;
62- hasCredentials : boolean ;
63- _tx ?: unknown ;
64- _signature ?: unknown ;
65- setTransaction : ( tx : unknown ) => void ;
66- } = {
67- _network : { } ,
68- _networkID : DEFAULT_NETWORK_ID ,
69- _blockchainID : Buffer . alloc ( EMPTY_BUFFER_SIZE ) ,
70- _assetId : Buffer . alloc ( EMPTY_BUFFER_SIZE ) ,
71- _fromAddresses : [ ] ,
72- _to : [ ] ,
73- _locktime : DEFAULT_LOCKTIME ,
74- _threshold : DEFAULT_THRESHOLD ,
75- _fee : { fee : AMOUNT_STRING_ZERO } ,
76- hasCredentials : false ,
77- setTransaction : function ( _tx : unknown ) {
78- this . _tx = _tx ;
79- } ,
80- } ;
51+ // TODO check _flrpTransaction type
52+ protected _flrpTransaction : any ;
53+
54+ public _network : FlareNetwork ;
55+ public _networkID : number ;
56+ public _blockchainID : Buffer ;
57+ public _assetId : Buffer ;
58+ public _fromAddresses : string [ ] ;
59+ public _to : string [ ] ;
60+ public _locktime : bigint ;
61+ public _threshold : number ;
62+ public _fee : { fee : string ; feeRate ?: string ; size ?: number } ;
63+ public hasCredentials : boolean ;
64+ public _tx ?: unknown ;
65+ public _signature ?: unknown ;
66+ public _type : TransactionType ;
67+ public _rewardAddresses : Buffer [ ] ;
8168
8269 constructor ( coinConfig : Readonly < CoinConfig > ) {
70+ super ( coinConfig ) ;
8371 this . _coinConfig = coinConfig ;
8472 }
8573
@@ -91,8 +79,8 @@ export abstract class AtomicTransactionBuilder {
9179 */
9280 protected getAssetId ( ) : Buffer {
9381 // Use the asset ID from transaction if already set
94- if ( this . transaction . _assetId && this . transaction . _assetId . length > 0 ) {
95- return this . transaction . _assetId ;
82+ if ( this . _assetId && this . _assetId . length > 0 ) {
83+ return this . _assetId ;
9684 }
9785
9886 // For native FLR transactions, return zero-filled buffer as placeholder
@@ -218,7 +206,7 @@ export abstract class AtomicTransactionBuilder {
218206 assetID : this . getAssetId ( ) ,
219207 output : {
220208 amount : changeAmount ,
221- addresses : this . transaction . _fromAddresses ,
209+ addresses : this . _fromAddresses ,
222210 threshold : 1 ,
223211 locktime : 0n ,
224212 } ,
@@ -326,8 +314,8 @@ export abstract class AtomicTransactionBuilder {
326314 } ;
327315
328316 // Store signature for FlareJS compatibility
329- this . transaction . _signature = signature ;
330- this . transaction . hasCredentials = true ;
317+ this . _signature = signature ;
318+ this . hasCredentials = true ;
331319
332320 return this ;
333321 } catch ( error ) {
@@ -356,7 +344,7 @@ export abstract class AtomicTransactionBuilder {
356344 _type : this . transactionType ,
357345 signature : [ ] as string [ ] ,
358346
359- fromAddresses : this . transaction . _fromAddresses ,
347+ fromAddresses : this . _fromAddresses ,
360348 validationErrors : [ ] ,
361349
362350 // FlareJS methods with atomic support
@@ -374,7 +362,7 @@ export abstract class AtomicTransactionBuilder {
374362 id : `${ FLARE_ATOMIC_PREFIX } ${ Date . now ( ) } ` ,
375363 changeOutputs : [ ] ,
376364 changeAmount : AMOUNT_STRING_ZERO ,
377- fee : { fee : this . transaction . _fee . fee } ,
365+ fee : { fee : this . _fee . fee } ,
378366 } ) ,
379367
380368 isTransactionForCChain : false ,
@@ -383,7 +371,7 @@ export abstract class AtomicTransactionBuilder {
383371 } ,
384372 inputs : ( ) => [ ] ,
385373 outputs : ( ) => [ ] ,
386- fee : ( ) => ( { fee : this . transaction . _fee . fee } ) ,
374+ fee : ( ) => ( { fee : this . _fee . fee } ) ,
387375 feeRate : ( ) => 0 ,
388376 id : ( ) => `${ FLARE_ATOMIC_PREFIX } ${ Date . now ( ) } ` ,
389377 type : this . transactionType ,
@@ -412,12 +400,76 @@ export abstract class AtomicTransactionBuilder {
412400 id : `${ FLARE_ATOMIC_PARSED_PREFIX } ${ Date . now ( ) } ` ,
413401 changeOutputs : [ ] ,
414402 changeAmount : AMOUNT_STRING_ZERO ,
415- fee : { fee : this . transaction . _fee . fee } ,
403+ fee : { fee : this . _fee . fee } ,
416404 } ;
417405 } catch ( error ) {
418406 throw new BuildTransactionError (
419407 `${ ERROR_ENHANCED_PARSE_FAILED } : ${ error instanceof Error ? error . message : ERROR_UNKNOWN } `
420408 ) ;
421409 }
422410 }
411+
412+ /** @inheritdoc */
413+ protected signImplementation ( { key } : BaseKey ) : BaseTransaction {
414+ this . _signer . push ( new KeyPair ( { prv : key } ) ) ;
415+ return this . transaction ;
416+ }
417+
418+ /** @inheritdoc */
419+ protected async buildImplementation ( ) : Promise < Transaction > {
420+ this . buildFlareTransaction ( ) ;
421+ this . transaction . setTransactionType ( this . transactionType ) ;
422+ if ( this . hasSigner ) {
423+ this . _signer . forEach ( ( keyPair ) => this . transaction . sign ( keyPair ) ) ;
424+ }
425+ return this . transaction ;
426+ }
427+
428+ /**
429+ * Builds the avax transaction. transaction field is changed.
430+ */
431+ protected abstract buildFlareTransaction ( ) : void ;
432+
433+ /**
434+ * Getter for know if build should sign
435+ */
436+ get hasSigner ( ) : boolean {
437+ return this . _signer !== undefined && this . _signer . length > 0 ;
438+ }
439+
440+ /** @inheritdoc */
441+ validateKey ( { key } : BaseKey ) : void {
442+ if ( ! new KeyPair ( { prv : key } ) ) {
443+ throw new BuildTransactionError ( 'Invalid key' ) ;
444+ }
445+ }
446+
447+ /** @inheritdoc */
448+ validateAddress ( address : BaseAddress , addressFormat ?: string ) : void {
449+ if ( ! utils . isValidAddress ( address . address ) ) {
450+ throw new BuildTransactionError ( 'Invalid address' ) ;
451+ }
452+ }
453+
454+ /** @inheritdoc */
455+ validateValue ( value : BigNumber ) : void {
456+ if ( value . isLessThan ( 0 ) ) {
457+ throw new BuildTransactionError ( 'Value cannot be less than zero' ) ;
458+ }
459+ }
460+
461+ /**
462+ * Check the raw transaction has a valid format in the blockchain context, throw otherwise.
463+ * It overrides abstract method from BaseTransactionBuilder
464+ *
465+ * @param rawTransaction Transaction in any format
466+ */
467+ validateRawTransaction ( rawTransaction : string ) : void {
468+ utils . validateRawTransaction ( rawTransaction ) ;
469+ }
470+
471+ /** @inheritdoc */
472+ validateTransaction ( transaction ?: Transaction ) : void {
473+ // throw new NotImplementedError('validateTransaction not implemented');
474+ }
423475}
0 commit comments