From b776c296ad6c5a4de4cf587af11a497d96038274 Mon Sep 17 00:00:00 2001 From: Pouria Date: Mon, 30 May 2022 12:13:46 +0430 Subject: [PATCH 1/4] enhance bitcoin and ethereum models --- src/models/BitcoinWalletModel.ts | 11 ++-- src/models/EthereumWalletModel.ts | 13 ++-- src/models/OmniWalletModel.ts | 11 ++-- src/wallet/BitcoinWallet.ts | 106 +++++++++++++++--------------- src/wallet/EthereumWallet.ts | 26 ++++---- 5 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/models/BitcoinWalletModel.ts b/src/models/BitcoinWalletModel.ts index dbe8bf3..ef514ef 100644 --- a/src/models/BitcoinWalletModel.ts +++ b/src/models/BitcoinWalletModel.ts @@ -1,7 +1,7 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -17,6 +17,7 @@ */ import { AddressModel } from "./Prokey"; +import {BaseAccountInfoModel} from "./GeneralModels"; /** * For account discovery, BitcoinAccountAddressReq should be used as starting point @@ -27,7 +28,7 @@ export interface BitcoinDiscoveryWalletReq { path?: Array | string, publicKey?: string, pubkeyIndex?: number, - isGetUtxo?: boolean, + isGetUtxo?: boolean, } /** @@ -43,12 +44,10 @@ export interface BitcoinWalletModel { /** * Each wallet contains a list of accounts * Most of the times there are just one account - * + * * Result of account discovery is total account balance and list of Addresses with all info */ -export interface BitcoinAccountInfo { - balance: number, - accountIndex: number, +export interface BitcoinAccountInfo extends BaseAccountInfoModel{ isDiscoveryFinished: boolean, addresses: Array, changeAddresses: Array, diff --git a/src/models/EthereumWalletModel.ts b/src/models/EthereumWalletModel.ts index ab15e89..8ad7b0d 100644 --- a/src/models/EthereumWalletModel.ts +++ b/src/models/EthereumWalletModel.ts @@ -1,7 +1,7 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -17,6 +17,7 @@ */ import { AddressModel } from "./Prokey"; +import {BaseAccountInfoModel} from "./GeneralModels"; export interface EthereumAddressInfo { @@ -40,12 +41,10 @@ export interface EthereumWalletModel { /** * Each wallet contains a list of accounts * Most of the times there is just one account - * + * * Result of account discovery is total account balance and list of Addresses with all info */ -export interface EthereumAccountInfo { - balance: number, - accountIndex: number, +export interface EthereumAccountInfo extends BaseAccountInfoModel { nonce?: number, addressModel?: AddressModel, transactions?: Array, @@ -61,7 +60,7 @@ export interface EthereumTransaction { gasPrice?: number, block?: number, nonce?: number, - + //! ERC20 logIndex?: number, } @@ -75,4 +74,4 @@ export interface EthereumTransaction { received?: string, sent?: string, fee?: number, -} \ No newline at end of file +} diff --git a/src/models/OmniWalletModel.ts b/src/models/OmniWalletModel.ts index 762e8d1..96b72c2 100644 --- a/src/models/OmniWalletModel.ts +++ b/src/models/OmniWalletModel.ts @@ -1,9 +1,9 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * Hadi Robati, hadi@prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -19,6 +19,7 @@ */ import { AddressModel } from "./Prokey"; +import {BaseAccountInfoModel} from "./GeneralModels"; /** * This is the result of account discovery @@ -30,9 +31,7 @@ export interface OmniWalletModel { accounts?: Array, } -export interface OmniAccountInfo { - balance: number, - accountIndex: number, +export interface OmniAccountInfo extends BaseAccountInfoModel { addressModel?: AddressModel, trKeys?: Array } @@ -66,4 +65,4 @@ export interface OmniTxInfo { valid: boolean, invalidReason?: string, timeStamp: number, -} \ No newline at end of file +} diff --git a/src/wallet/BitcoinWallet.ts b/src/wallet/BitcoinWallet.ts index 8aed01f..11dc29b 100644 --- a/src/wallet/BitcoinWallet.ts +++ b/src/wallet/BitcoinWallet.ts @@ -1,9 +1,9 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * Hadi Robati, hadi@prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -36,14 +36,16 @@ import { } from '../models/Prokey'; import { BaseWallet } from './BaseWallet'; import { MyConsole } from '../utils/console' +import {BaseWalletModel} from "../models/GeneralModels"; +import {BitcoinAccountInfo} from "../models/BitcoinWalletModel"; var WAValidator = require('multicoin-address-validator'); /** - * If you wish to discover and use the bitcoin wallet, you need to use this class. + * If you wish to discover and use the bitcoin wallet, you need to use this class. * This class can be used for all bitcoin based coins. */ export class BitcoinWallet extends BaseWallet { - private _bitcoinWallet!: WalletModel.BitcoinWalletModel + private _bitcoinWallet!: BaseWalletModel private _blockchain: BitcoinBlockChain; @@ -57,7 +59,7 @@ export class BitcoinWallet extends BaseWallet { _TX_DEFAULT_OUTPUT_SIZE = 32; // TX Details - // Version(4) + Marker(1) + Flag(1) + InputCout(usually 1B) + OutputCount(usually 1B) + LockTime(4) + // Version(4) + Marker(1) + Flag(1) + InputCout(usually 1B) + OutputCount(usually 1B) + LockTime(4) _TX_DEFAULT_OVERHEAD_SIZE = 12; /** @@ -76,16 +78,16 @@ export class BitcoinWallet extends BaseWallet { * Start searching blockchain to discovery(find) the wallet * @param accountFindCallBack is an optional callback function, this function will be called when an account discovered * @param allAccounts true means discover all account, false means discover only the first account - * @returns BitcoinWallet with all accounts + * @returns BitcoinWallet with all accounts */ - public async StartDiscovery(accountFindCallBack?: (accountInfo: WalletModel.BitcoinAccountInfo) => void, allAccounts = false): Promise{ + public async StartDiscovery(accountFindCallBack?: (accountInfo: WalletModel.BitcoinAccountInfo) => void, allAccounts = false): Promise>{ this._bitcoinWallet = { totalBalance: 0, } - this._bitcoinWallet.accounts = new Array(); + this._bitcoinWallet.accounts = new Array(); - return new Promise(async (resolve, reject) => { + return new Promise>(async (resolve, reject) => { try { let accountNumber = 0; @@ -129,12 +131,12 @@ export class BitcoinWallet extends BaseWallet { * Get last discovered wallet * @returns the last discovered wallet */ - public GetWallet(): WalletModel.BitcoinWalletModel { + public GetWallet(): BaseWalletModel { return this._bitcoinWallet; } /** - * Get blockchain + * Get blockchain */ public GetBlockChain(): BitcoinBlockChain { return this._blockchain; @@ -145,7 +147,7 @@ export class BitcoinWallet extends BaseWallet { * @param accountNumber Account Number * @param accountInfo account info which were discovered by AccountDiscovert */ - async DiscoverChanges(accountNumber: number, + async DiscoverChanges(accountNumber: number, accountInfo: WalletModel.BitcoinAccountInfo) { var finished: boolean = false; @@ -168,7 +170,7 @@ export class BitcoinWallet extends BaseWallet { // Getting addresses from Prokey let addresses = await super.GetAddresses(justPaths); - // Creating request parameter + // Creating request parameter let reqAddInfo: Array = addresses.map(a => { return { address: a.address, @@ -209,7 +211,7 @@ export class BitcoinWallet extends BaseWallet { let startIndex = 0; - do { + do { let justPaths : Array> = []; @@ -261,7 +263,7 @@ export class BitcoinWallet extends BaseWallet { if(accountInfo.lastUnusedAddress != null && af.exist == true){ accountInfo.lastUnusedAddress = undefined; } - + // If there is any transaction for addresses, we have to search for next (20) addresses again // This process will be finished when there is no transaction if(af.exist){ @@ -313,7 +315,7 @@ export class BitcoinWallet extends BaseWallet { // For every transaction received from the blockchain // These transaction can be either 'send' or 'receive' // If any of account addresses appeares on any outputs, this is a 'receive' tx - // On the other hand, if any of account addresses appeares on any inputs, this is 'send' tx + // On the other hand, if any of account addresses appeares on any inputs, this is 'send' tx listOfTransactions.forEach(tx => { let totalReceived = 0; let totalSent = 0; @@ -352,7 +354,7 @@ export class BitcoinWallet extends BaseWallet { isFromOwnWallet = true; break; } - + if(account.changeAddresses.find(changeAddress => changeAddress.address == tx.inputs[k].address)){ isFromOwnWallet = true; break; @@ -360,7 +362,7 @@ export class BitcoinWallet extends BaseWallet { } let status : 'RECEIVED' | 'RECEIVED_FROM_OWN' | 'OMNI_RECEIVED' | 'OMNI_CHANGE' = 'RECEIVED'; - + if(isOpReturn) { if(tx.outputs[i].valueNumber == 546) { status = 'OMNI_RECEIVED'; @@ -411,7 +413,7 @@ export class BitcoinWallet extends BaseWallet { if(addressInInputs == undefined) { addressInInputs = account.changeAddresses.find(ca => ca.address == tx.inputs[i].address); } - + if(addressInInputs != undefined) { //! If there is any OP_RETURN output @@ -419,7 +421,7 @@ export class BitcoinWallet extends BaseWallet { //! If there is any Dust value in outputs let isDust = false; - //! Check if there is a OP_RETURN + //! Check if there is a OP_RETURN for(let k = 0; k { totalSend += element.value; @@ -566,46 +568,46 @@ export class BitcoinWallet extends BaseWallet { //! Input addresses let utxoBal = 0; - + // Check if we can handle this transaction only with one Input if (sortedUtoxs[0][0].amount >= totalSend + txFee) { let i = 1; for (; i < sortedUtoxs.length; i++) { - if (sortedUtoxs[i][0].amount < totalSend + txFee) + if (sortedUtoxs[i][0].amount < totalSend + txFee) break; } // i is the best utxo for input let utxo = sortedUtoxs[i - 1]; - if (utxo[1] as number[]) { + if (utxo[1] as number[]) { tx.inputs.push({ - address_n: (utxo[1] as number[]), - prev_hash: utxo[0].hash, + address_n: (utxo[1] as number[]), + prev_hash: utxo[0].hash, prev_index: utxo[0].index, amount: utxo[0].amount.toString() - }); + }); utxoBal = utxo[0].amount; } } else { - // We need multi input to handle this transaction + // We need multi input to handle this transaction for (let i = 0; i < sortedUtoxs.length; i++) { let utxo = sortedUtoxs[i]; - if (utxo[1] as number[]) { - tx.inputs.push({address_n: (utxo[1] as number[]), - prev_hash: utxo[0].hash, + if (utxo[1] as number[]) { + tx.inputs.push({address_n: (utxo[1] as number[]), + prev_hash: utxo[0].hash, prev_index: utxo[0].index, amount: utxo[0].amount.toString() - }); + }); utxoBal += utxo[0].amount; - } + } if (utxoBal >= totalSend + txFee) break; } } - //! Load previous transactions + //! Load previous transactions await this.LoadPrevTx(tx, coinInfo.timestamp); //! Set the TX's outputs @@ -632,7 +634,7 @@ export class BitcoinWallet extends BaseWallet { } //! Add change - fee - let change = utxoBal - totalSend - txFee; + let change = utxoBal - totalSend - txFee; let changePaths = PathUtil.GetBipPath( CoinBaseType.BitcoinBase, // Coin Type @@ -645,7 +647,7 @@ export class BitcoinWallet extends BaseWallet { //! No change if the change is less than dust if(coinInfo.dust_limit != null) { - if(change >= coinInfo.dust_limit) { + if(change >= coinInfo.dust_limit) { tx.outputs.push({ address_n: changePaths.path, amount: change.toFixed(0), @@ -734,7 +736,7 @@ export class BitcoinWallet extends BaseWallet { * Estimate the length of a transaction * @param receivers List of receivers (outputs) * @param acc The account number you wish to send from - * @param txFees The current fee rated + * @param txFees The current fee rated */ public CalculateTxLen(receivers: Array, acc: WalletModel.BitcoinAccountInfo, txFees: WalletModel.BitcoinFee): number { if(this._bitcoinWallet.accounts == null){ @@ -745,11 +747,11 @@ export class BitcoinWallet extends BaseWallet { s = 10 + 148×n + 34×t, ±n where n is the number of inputs and t is the number of outputs. The input contribution accounts for outpoint (36 bytes) script length (1 byte), - script (107 bytes), and sequence (4 bytes). The output contribution accounts for the value field (8 bytes), script length (1 byte), + script (107 bytes), and sequence (4 bytes). The output contribution accounts for the value field (8 bytes), script length (1 byte), and script (25 bytes). - For example, a one-input, one-output transaction would require on average 193 bytes (10 + 148 + 35). - A more realistic one-input, two-output transaction that allowed the collection of change would require on average 226 bytes (10 + 148 + 2×34). + For example, a one-input, one-output transaction would require on average 193 bytes (10 + 148 + 35). + A more realistic one-input, two-output transaction that allowed the collection of change would require on average 226 bytes (10 + 148 + 2×34). A six-input, six-output CoinJoin transaction would require on average 1,102 bytes (10 + 6×148 + 6×34), and so on. */ //! We should calculate the size of this transaction to calculate the actual fee @@ -790,24 +792,24 @@ export class BitcoinWallet extends BaseWallet { { let i = 1; for (; i < sortedUtoxs.length; i++) { - if (sortedUtoxs[i][0].amount < totalSend + (txFees.economy * (txLen + this._TX_DEFAULT_INPUT_SIZE))) + if (sortedUtoxs[i][0].amount < totalSend + (txFees.economy * (txLen + this._TX_DEFAULT_INPUT_SIZE))) break; } // i is the best utxo for input let utxo = sortedUtoxs[i - 1]; - if (utxo[1] as number[]) { + if (utxo[1] as number[]) { txLen += this._TX_DEFAULT_INPUT_SIZE; } } else { - // We need multi input to handle this transaction + // We need multi input to handle this transaction for (let i = 0; i < sortedUtoxs.length; i++) { let utxo = sortedUtoxs[i]; - if (utxo[1] as number[]) { + if (utxo[1] as number[]) { txLen += this._TX_DEFAULT_INPUT_SIZE; utxoBal += utxo[0].amount; - } + } if (utxoBal >= totalSend + (txFees.economy * txLen)) break; @@ -838,7 +840,7 @@ export class BitcoinWallet extends BaseWallet { if(!WAValidator.findCurrency(symbol)){ return false; } - + if(coinInfo.test != undefined && coinInfo.test == true) { if(WAValidator.validate(address, symbol, 'testnet')) { return true; @@ -848,13 +850,13 @@ export class BitcoinWallet extends BaseWallet { return true; } } - + return false; } /** * Get List of sorted UTXO account - * @param acc account to get UTXO from + * @param acc account to get UTXO from */ private CreateSortedUtxoList(acc: WalletModel.BitcoinAccountInfo): Array<[WalletModel.BitcoinUtxo, Array | string | undefined]>{ //! Create a utxos list @@ -862,7 +864,7 @@ export class BitcoinWallet extends BaseWallet { acc.addresses.forEach(element => { let path = (element.addressModel == undefined) ? undefined : element.addressModel.path; if (element.exist && element.txInfo != undefined && element.txInfo.utxOs) - element.txInfo.utxOs.forEach(utxo => { + element.txInfo.utxOs.forEach(utxo => { utxos.push([utxo, path]); }); }); @@ -876,7 +878,7 @@ export class BitcoinWallet extends BaseWallet { }); let sortedUtoxs = utxos.sort( (a,b) => { - if (a[0].amount > b[0].amount) + if (a[0].amount > b[0].amount) return -1; else if( a[0].amount == b[0].amount) return 0; @@ -889,7 +891,7 @@ export class BitcoinWallet extends BaseWallet { /** * Loading previous transaction of each input(s). - * @param tx Bitcoin transaction + * @param tx Bitcoin transaction */ private async LoadPrevTx(tx: BitcoinTx, timestamp: boolean) { if(tx.inputs == undefined || tx.inputs.length == 0){ @@ -903,7 +905,7 @@ export class BitcoinWallet extends BaseWallet { { let txHashIds = ""; let perRequest = (n > 10) ? 10 : n; - + for(let j=0; j; _gasLimit: number = 21000; _ethBlockChain: EthereumBlockChain; _isErc20 = false; @@ -73,16 +75,16 @@ export class EthereumWallet extends BaseWallet { } /** - * Start searching blockchain to discovery(find) the wallet + * Start searching blockchain to discovery(find) the wallet * @param accountFindCallBack is an optional callback function, this function will be called when an account discovered * @returns Ethereum Wallet Model */ - public async StartDiscovery(accountFindCallBack?: (accountInfo: WalletModel.EthereumAccountInfo) => void, allAccounts = false): Promise { + public async StartDiscovery(accountFindCallBack?: (accountInfo: WalletModel.EthereumAccountInfo) => void, allAccounts = false): Promise> { this._ethereumWallet = { totalBalance: 0, } - return new Promise(async (resolve, reject) => { + return new Promise>(async (resolve, reject) => { let an = 0; try { @@ -101,7 +103,7 @@ export class EthereumWallet extends BaseWallet { accountFindCallBack(account); } - // update the total wallet balance + // update the total wallet balance this._ethereumWallet.totalBalance += account.balance; // If there is no transaction, the discovery finished @@ -261,7 +263,7 @@ export class EthereumWallet extends BaseWallet { } /** - * This function will prepare raw RLP encoded transaction to be sent + * This function will prepare raw RLP encoded transaction to be sent * @param transaction Signed Transaction * @param signedValues Signature values, R,S and V */ @@ -298,9 +300,9 @@ export class EthereumWallet extends BaseWallet { /** * To get a list of transaction to show to end user on the UI - * @param accountNumber - * @param startIndex - * @param numberOfTransactions + * @param accountNumber + * @param startIndex + * @param numberOfTransactions */ public async GetTransactionViewList(accountNumber: number = 0, startIndex: number = 0, numberOfTransactions: number): Promise> { if (this._ethereumWallet.accounts == null) { From 955d67b1ca618908f54552c5be0fd9cc2f58139a Mon Sep 17 00:00:00 2001 From: Pouria Date: Mon, 30 May 2022 12:23:45 +0430 Subject: [PATCH 2/4] add general model --- src/models/GeneralModels.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/models/GeneralModels.ts diff --git a/src/models/GeneralModels.ts b/src/models/GeneralModels.ts new file mode 100644 index 0000000..fddbb49 --- /dev/null +++ b/src/models/GeneralModels.ts @@ -0,0 +1,9 @@ +export interface BaseWalletModel { + totalBalance: number, + accounts?: Array, +} + +export interface BaseAccountInfoModel { + balance: number, + accountIndex: number +} From be10a76da824baa34eaae0a296fe0b01ba3c890e Mon Sep 17 00:00:00 2001 From: Pouria Date: Sun, 5 Jun 2022 08:03:33 +0430 Subject: [PATCH 3/4] change ripple wallet functionality --- .../src/ripple/ProkeyRippleBlockChain.ts | 14 ++-- .../servers/prokey/src/ripple/RippleModel.ts | 18 ++--- src/wallet/RippleWallet.ts | 81 ++++++++++++------- 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/src/blockchain/servers/prokey/src/ripple/ProkeyRippleBlockChain.ts b/src/blockchain/servers/prokey/src/ripple/ProkeyRippleBlockChain.ts index 26bd917..31f6436 100644 --- a/src/blockchain/servers/prokey/src/ripple/ProkeyRippleBlockChain.ts +++ b/src/blockchain/servers/prokey/src/ripple/ProkeyRippleBlockChain.ts @@ -1,7 +1,7 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -17,7 +17,7 @@ */ import { ProkeyBaseBlockChain } from "../ProkeyBaseBlockChain"; -import { RippleAccountInfo, RippleFee, RippleTransactionDataInfo } from "./RippleModel"; +import { RippleAccount, RippleFee, RippleTransactionDataInfo } from "./RippleModel"; import {RequestAddressInfo} from "../../../../../models/GenericWalletModel"; import * as Utils from '../../../../../utils/utils'; @@ -36,10 +36,10 @@ export class ProkeyRippleBlockchain extends ProkeyBaseBlockChain { * @param reqAddress Address * @returns Ripple account info */ - public async GetAddressInfo(reqAddress: RequestAddressInfo): Promise - { + public async GetAddressInfo(reqAddress: RequestAddressInfo): Promise + { try { - return await this.GetFromServer(`address/${this._coinName}/${reqAddress.address}`); + return await this.GetFromServer(`address/${this._coinName}/${reqAddress.address}`); } catch (error) { return null; } @@ -72,7 +72,7 @@ export class ProkeyRippleBlockchain extends ProkeyBaseBlockChain { /** * Broadcasting the transaction * @param data Signed data to be broadcasted to network - * @returns + * @returns */ public async BroadCastTransaction(data: string): Promise { let data_any = data as any; @@ -92,4 +92,4 @@ export class ProkeyRippleBlockchain extends ProkeyBaseBlockChain { private async SendTransaction(data: string): Promise { return await this.GetFromServer(`Transaction/send/${this._coinName}/${data}`); } -} \ No newline at end of file +} diff --git a/src/blockchain/servers/prokey/src/ripple/RippleModel.ts b/src/blockchain/servers/prokey/src/ripple/RippleModel.ts index 70bae23..1fd86a2 100644 --- a/src/blockchain/servers/prokey/src/ripple/RippleModel.ts +++ b/src/blockchain/servers/prokey/src/ripple/RippleModel.ts @@ -1,7 +1,7 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -18,15 +18,15 @@ import { AddressModel } from "../../../../../models/Prokey"; -export interface RippleAccountInfo +export interface RippleAccount { Account: string, AccountTxnID?: string, Balance?: string, - Domain?: null, - EmailHash?: null, - MessageKey?: null, - RegularKey?: null, + Domain?: string, + EmailHash?: string, + MessageKey?: string, + RegularKey?: string, OwnerCount: number, PreviousTxnID: string, PreviousTxnLgrSeq: number, @@ -62,7 +62,7 @@ export interface RippleTransactionDataInfo validated: boolean } -export interface RippleDrop +export interface RippleDrop { base_fee: string, median_fee: string, @@ -70,7 +70,7 @@ export interface RippleDrop open_ledger_fee: string } -export interface RippleFee +export interface RippleFee { current_ledger_size: string, current_queue_size: string, @@ -81,4 +81,4 @@ export interface RippleFee max_queue_size: string, status: string, validated: boolean -} \ No newline at end of file +} diff --git a/src/wallet/RippleWallet.ts b/src/wallet/RippleWallet.ts index a4df4d9..ab22b5b 100644 --- a/src/wallet/RippleWallet.ts +++ b/src/wallet/RippleWallet.ts @@ -1,7 +1,7 @@ /* * This is part of PROKEY HARDWARE WALLET project * Copyright (C) Prokey.io - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,64 +16,87 @@ * along with this program. If not, see . */ -import { RippleAccountInfo, RippleFee, RippleTransactionDataInfo } from "../blockchain/servers/prokey/src/ripple/RippleModel"; +import { RippleAccount, RippleFee, RippleTransactionDataInfo } from "../blockchain/servers/prokey/src/ripple/RippleModel"; import { CoinBaseType } from "../coins/CoinInfo"; import { Device } from "../device/Device"; import { RippleCoinInfoModel } from "../models/CoinInfoModel"; import { BaseWallet } from "./BaseWallet"; import * as PathUtil from '../utils/pathUtils'; -import { RippleAddress, RippleSignedTx, RippleTransaction } from "../models/Prokey"; +import {RippleAddress, RippleSignedTx, RippleTransaction} from "../models/Prokey"; import {ProkeyRippleBlockchain} from "../blockchain/servers/prokey/src/ripple/ProkeyRippleBlockChain"; +import {BaseWalletModel} from "../models/GeneralModels"; +import {RippleAccountInfo} from "../models/RippleWalletModel"; var WAValidator = require('multicoin-address-validator'); export class RippleWallet extends BaseWallet { - _block_chain : ProkeyRippleBlockchain; - _accounts: Array; + private _block_chain : ProkeyRippleBlockchain; + private _rippleWallet!: BaseWalletModel; constructor(device: Device, coinName: string) { - super(device, coinName, CoinBaseType.Ripple); + super(device, coinName, CoinBaseType.Ripple); this._block_chain = new ProkeyRippleBlockchain(this.GetCoinInfo().shortcut); - this._accounts = []; + this._rippleWallet = {totalBalance: 0}; } - + public IsAddressValid(address: string): boolean { return WAValidator.validate(address, "xrp"); } public async StartDiscovery( accountFindCallBack?: (accountInfo: RippleAccountInfo) => void - ): Promise> + ): Promise> { - return new Promise>(async (resolve, reject) => { - let an = 0; - this._accounts = new Array(); + + return new Promise>(async (resolve, reject) => { + let accountIndex = 0; + this._rippleWallet = {totalBalance: 0}; + this._rippleWallet.accounts = new Array(); do { - let account = await this.GetAccountInfo(an); + let account = await this.GetAccountInfo(accountIndex); if (account == null) { // there is nothing here - return resolve(this._accounts); + return resolve(this._rippleWallet); } - this._accounts.push(account); + let rippleAccountInfo = { + accountIndex: accountIndex, + balance: account.Balance ? +account.Balance : 0, + Account: account.Account, + AccountTxnID: account.AccountTxnID, + Domain: account.Domain, + EmailHash: account.EmailHash, + MessageKey: account.MessageKey, + RegularKey: account.RegularKey, + OwnerCount: account.OwnerCount, + PreviousTxnID: account.PreviousTxnID, + PreviousTxnLgrSeq: account.PreviousTxnLgrSeq, + Sequence: account.Sequence, + TickSize: account.TickSize, + TransferRate: account.TransferRate, + LedgerEntryType: account.LedgerEntryType, + Flags: account.Flags, + index: account.index, + }; + this._rippleWallet.accounts.push(rippleAccountInfo); if (accountFindCallBack) { - accountFindCallBack(account); + accountFindCallBack(rippleAccountInfo); } - an++; + accountIndex++; } while(true); }); } // Get ripple account info from blockchain - private async GetAccountInfo(accountNumber: number): Promise { + private async GetAccountInfo(accountNumber: number): Promise { let path = PathUtil.GetBipPath( CoinBaseType.Ripple, accountNumber, super.GetCoinInfo() ) - + let address = await this.GetAddress(path.path, false); //! Save address @@ -81,11 +104,11 @@ export class RippleWallet extends BaseWallet { //! Getting address(account) info. from blockchain let addressInfo = await this._block_chain.GetAddressInfo({address: address.address}); - + //! Add AddressModel if(addressInfo != null){ addressInfo.addressModel = path; - } + } return addressInfo; } @@ -102,20 +125,20 @@ export class RippleWallet extends BaseWallet { public GenerateTransaction(toAccount: string, amount: number, accountNumber: number, selectedFee: string, destinationTag?: number): RippleTransaction { // Validate accountNumber - if(accountNumber >= this._accounts.length){ + if(!this._rippleWallet.accounts || accountNumber >= this._rippleWallet.accounts.length){ throw new Error('Account number is wrong'); } // Check balance let bal = 0; - var acc = this._accounts[accountNumber]; - if (acc != null && acc.Balance != null) { - bal = +acc.Balance; + var acc = this._rippleWallet.accounts[accountNumber]; + if (acc != null && acc.balance != null) { + bal = +acc.balance; } let ci = super.GetCoinInfo() as RippleCoinInfoModel; - bal = bal + bal = bal - ci.min_balance // 20 XRP for reserve - amount - (+selectedFee); @@ -127,14 +150,14 @@ export class RippleWallet extends BaseWallet { accountNumber, ci ) - + let tx: RippleTransaction = { address_n: path.path, fee: +selectedFee, - sequence: this._accounts[accountNumber].Sequence, + sequence: this._rippleWallet.accounts[accountNumber].Sequence, payment: { amount: amount, - destination: toAccount, + destination: toAccount, } }; if (destinationTag) From 516f245641620b067d36e8d0c0318d2176077ed3 Mon Sep 17 00:00:00 2001 From: Pouria Date: Sun, 5 Jun 2022 08:04:57 +0430 Subject: [PATCH 4/4] add ripple wallet model --- src/models/RippleWalletModel.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/models/RippleWalletModel.ts diff --git a/src/models/RippleWalletModel.ts b/src/models/RippleWalletModel.ts new file mode 100644 index 0000000..e0e0a7d --- /dev/null +++ b/src/models/RippleWalletModel.ts @@ -0,0 +1,23 @@ +import {AddressModel} from "./Prokey"; +import {BaseAccountInfoModel} from "./GeneralModels"; + +export interface RippleAccountInfo extends BaseAccountInfoModel +{ + Account: string, + AccountTxnID?: string, + Domain?: string, + EmailHash?: string, + MessageKey?: string, + RegularKey?: string, + OwnerCount: number, + PreviousTxnID: string, + PreviousTxnLgrSeq: number, + Sequence: number, + TickSize: number, + TransferRate: number, + LedgerEntryType: string, + Flags: number, + index: string, + + addressModel?: AddressModel, +}