Skip to content

Examples: Helper Classes

Chun Lam edited this page Feb 21, 2024 · 4 revisions
import { NetworkType, BlockInfo, Transaction, SignedTransaction, PublicAccount, BlockHttp, NetworkHttp, Listener, TransactionHttp, NamespaceHttp } from "tsjs-xpx-chain-sdk";
import { firstValueFrom } from "rxjs"

export class NetworkProperties {
    public generationHash: string;
    public networkType: NetworkType;
    public nemesisBlockInfo: BlockInfo;

    constructor(nemesisBlockInfo: BlockInfo) {
        this.generationHash = nemesisBlockInfo.generationHash;
        this.networkType = nemesisBlockInfo.networkType;
        // store also the whole network info, if we need more information later on
        this.nemesisBlockInfo = nemesisBlockInfo;
    }
}

class ApiEndpoint {
    private _block: BlockHttp;
    private _listener: Listener;
    private _namespace: NamespaceHttp;
    private _network: NetworkHttp;
    private _transaction: TransactionHttp;

    constructor(public readonly url) {

    }
    public get block() {
        if (! this._block) {
            this._block = new BlockHttp(this.url, this.network);
        }
        return this._block;
    }
    public get listener() {
        if (! this._listener) {
            this._listener = new Listener(this.url);
        }
        return this._listener;
    }
    public get namespace() {
        if (! this._namespace) {
            this._namespace = new NamespaceHttp(this.url, this.network);
        }
        return this._namespace;
    }
    public get network() {
        if (! this._network) {
            this._network = new NetworkHttp(this.url);
        }
        return this._network;
    }
    public get transaction() {
        if (! this._transaction) {
            this._transaction = new TransactionHttp(this.url);
        }
        return this._transaction;
    }
}

export class Network {
    private _networkProperties: Promise<NetworkProperties>;
    private _api: ApiEndpoint;

    constructor(
        apiUrl: string
    ) {
        this._api = new ApiEndpoint(apiUrl);
    }

    public get api() {
        return this._api;
    }

    public get networkProperties() {
        if (! this._networkProperties) {

            this._networkProperties = firstValueFrom(this.api.block.getBlockByHeight(1))
                .then(nemesisBlockInfo => {
                    return new NetworkProperties(nemesisBlockInfo);
                });
        };
        return this._networkProperties;
    }

    public announceAndWaitForConfirmation(signedTx: SignedTransaction, isAggregateBonded = false) {
        return new Promise<Transaction>((resolve, reject) => {
            this.api.listener.open().then(() => {
                const status = this.api.listener.status(PublicAccount.createFromPublicKey(signedTx.signer, signedTx.networkType).address).subscribe(txStatusError => {
                    if (txStatusError.hash === signedTx.hash) {
                        console.error(txStatusError);
                        sub.unsubscribe();
                        status.unsubscribe();
                        reject(txStatusError.status);
                    }
                });
                const sub = this.api.listener.confirmed(PublicAccount.createFromPublicKey(signedTx.signer, signedTx.networkType).address).subscribe({
                    next: confirmedTx => {
                        if (confirmedTx && confirmedTx.transactionInfo && confirmedTx.transactionInfo.hash === signedTx.hash) {
                            // console.log('confirmed: ' + JSON.stringify(confirmedTx));
                            sub.unsubscribe();
                            status.unsubscribe();
                            resolve(confirmedTx);
                        }
                    }, 
                    error: error => {
                        // console.error('subscription failed');
                        if (sub) {
                            sub.unsubscribe();
                        }
                        if (status) {
                            status.unsubscribe();
                        }
                        reject(error);
                    }, 
                    complete: () => {
                        // console.log('subscription finished');
                        if (sub){
                            sub.unsubscribe();
                        }
                        if (status) {
                            status.unsubscribe();
                        }
                    }
                });

                if (isAggregateBonded) {
                    this.api.transaction.announceAggregateBonded(signedTx).subscribe({
                        next(txAnnounceResponse){
                        // console.log('announced');
                        }, 
                        error(error){ // error
                            // console.error('announce error');
                            sub.unsubscribe();
                            status.unsubscribe();
                            reject(error);
                        }, 
                        complete(){ // complete
                        // console.log('announce finished');
                        }
                    });
                } else {
                    this.api.transaction.announce(signedTx).subscribe({
                        next(txAnnounceResponse) {
                            console.log('announced'); 
                        }, 
                        error(error){ // error
                            // console.error('announce error');
                            sub.unsubscribe();
                            status.unsubscribe();
                            reject(error);
                        }, 
                        complete(){ // complete
                            // console.log('announce finished');
                        }
                    });
                }
            }).catch(reason => {
                reject(reason);
            });
        });
    }
}