UNPKG

bsv-p2p-wallet-uat

Version:
420 lines (367 loc) 11.9 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if ( e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]) ) t[p[i]] = s[p[i]]; } return t; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod, }; }; Object.defineProperty(exports, "__esModule", { value: true, }); const HDPrivateKey_1 = __importDefault(require("./HDPrivateKey")); const Blockchain_1 = __importDefault(require("./Blockchain")); const { SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS, } = require("bsv/lib/script/interpreter"); const _1 = require("."); const Tx_1 = require("./Utils/Tx"); const fs = __importDefault(require("fs")); const axios_1 = __importDefault(require("axios")); const BSVWallet_1 = __importDefault(require("./Wallet")); // const senderWallet = new BSVWallet.default({ key: "" }); // const walletSender = new Wallet({ key: "" }); class PeerToPeerWallet extends HDPrivateKey_1.default { constructor(_a) { var { key = "", keyFormat = "mnemonic", language = "ENGLISH", network = "testnet", } = _a, options = __rest(_a, ["key", "keyFormat", "language", "network"]); super( Object.assign( { key, keyFormat, language, network, }, options ) ); this.index = 0; this.blockchain = new Blockchain_1.default(network); this.cache = new _1.BlockchainCache(); this.api = axios_1.default.create({ baseURL: `https://api.whatsonchain.com/v1/bsv/main`, }); this.dbName = "PeerToPeer"; this.storeName = "Transactions"; this.existingTransactions = []; this.wallet = new BSVWallet_1.default({ key: "" }); } sync() { throw new Error("not yet implemented"); } sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async getBalance(walletAddress) { let dbValues = []; //await this.getDetails(existingTransactions); dbValues = await this.getExistingTransactions(walletAddress) console.log("Existing Transactions 2", dbValues); existingTransactions = dbValues.Transactions.map( x => x.value) let total = existingTransactions.reduce((a, b) => a + b, 0); return total; } remove_Pairs(inputArr) { var inputCount = {}; for (let index = 0; index < inputArr.length; index++) { if (inputArr[index] in inputCount) { inputCount[inputArr[index]] += 1; } else { inputCount[inputArr[index]] = 1; } } let ans = []; for (const [key, value] of Object.entries(inputCount)) { if (-key in inputCount) { let noOfTimes = inputCount[key] - inputCount[-key]; for (let index = 0; index < Math.abs(noOfTimes); index++) { ans.push(Math.abs(key)); } inputCount[-key] = 0; } else { for (let index = 0; index < inputCount[key]; index++) { ans.push(key); } } inputCount[key] = 0; } return ans.map((x) => Number(x)); } isBalanceEnough(allTransactions, amountToSend) { let sum = allTransactions.reduce((a, b) => a + b, 0); console.log("Balance = ", sum, " Amount to send = ", amountToSend); if (sum && amountToSend <= sum) { return true; } else { return false; } } async sendBitcoin(senderWallet, receiverWallet, sendBitcoinQuantity) { console.log("sender wallet", senderWallet); let existingTransactions = []; let dbValues = []; //await this.getDetails(existingTransactions); dbValues = await this.getExistingTransactions(senderWallet) console.log("Existing Transactions 2", dbValues); existingTransactions = dbValues.Transactions.map( x => x.value) if (!this.isBalanceEnough(existingTransactions, sendBitcoinQuantity)) { console.log("Balance is not enough. Returning") return null; } this.remove_Pairs(existingTransactions); //optimal array = result here let optimalArray = [] let temp = this.initOptimalArray(existingTransactions, sendBitcoinQuantity); if (temp.length == 0 || temp === undefined) return; optimalArray = temp[0]; let resultArrayUtxo = []; let transactions = []; try { let sum = optimalArray.reduce((a, b) => a + b, 0); for (let index = 0; index < optimalArray.length; index++) { const element = optimalArray[index]; console.log("Element ", element); let trUtxo = {}; trUtxo.to = receiverWallet; trUtxo.amount = element; resultArrayUtxo.push(trUtxo); let transaction = {} transaction.receiver= receiverWallet; transaction.amount = -1*element; transaction.wallet = senderWallet; transactions.push(transaction) } if ( sum != sendBitcoinQuantity ) { let trUtxo = {} trUtxo.to = senderWallet; trUtxo.amount = sum - sendBitcoinQuantity; resultArrayUtxo.push(trUtxo); let transaction = {} transaction.receiver= senderWallet; transaction.amount = sum - sendBitcoinQuantity; transaction.wallet = senderWallet; transactions.push(transaction) } console.log("ResultArray UTXO ", resultArrayUtxo); let tx = await this.wallet.signTx(resultArrayUtxo); transactions.forEach( x => x.txId = tx) dbValues.Transactions.push(transactions) console.log("dbValues.Transactions", dbValues.Transactions) this.addItemToDb(dbValues); return existingTransactions; } catch (error) { console.log(error); } } async createWallet() { this.wallet = new BSVWallet_1.default({ key: "" }); let address = await this.wallet.getAddress(); return address; } initOptimalArray(arr, sendBitcoinQuantity) { console.log(arr); let ans = []; this.subsetsSumGreaterThanK( arr, sendBitcoinQuantity, [], 0, 0, ans, Infinity ); console.log("Optimal ", ans.join(", ")); return ans; } subsetsSumGreaterThanK(nums, k, subset, csum, ind, ans, subSetSumClosestToK) { if (ind === nums.length) { if (csum >= k) { if (csum < subSetSumClosestToK) { ans[0] = [...subset]; subSetSumClosestToK = csum; } if (csum === subSetSumClosestToK && subset.length < ans[0].length) { ans[0] = [...subset]; } } return subSetSumClosestToK; } subset.push(nums[ind]); subSetSumClosestToK = this.subsetsSumGreaterThanK( nums, k, subset, csum + nums[ind], ind + 1, ans, subSetSumClosestToK ); subset.pop(); subSetSumClosestToK = this.subsetsSumGreaterThanK( nums, k, subset, csum, ind + 1, ans, subSetSumClosestToK ); return subSetSumClosestToK; } async decodeAllTransactions(wallet) { //await this.getDetails(existingTransactions); let dbValues = []; dbValues = await this.getExistingTransactions(wallet) console.log("Decoding All Transactions ", dbValues); var result = [] let existingTransactions = [] dbValues.Transactions.forEach( x => { if( Array.isArray(x) ) existingTransactions.push(x[0].txId); else existingTransactions.push(x.txId) }); existingTransactions.map( async (x) => { console.log("X", x) if ( x != "") { let tx = await this.blockchain.getTxDecode(x) await this.sleep(2000) console.log("Transaction ", tx) result.push(tx) } }); return result; } async initIndexedDb(idb) { if (!idb) { console.log("This browser doesn't support IndexedDB"); return false; } this.idb = idb; const request = idb.open(this.dbName, 1); request.onerror = async (event) => { console.error("An error occurred with IndexedDB"); console.error(event); return false; }; request.onupgradeneeded = async (event) => { console.log(event); const db = request.result; if (!db.objectStoreNames.contains(this.storeName)) { const objectStore = await db.createObjectStore(this.storeName, { keyPath: "wallet", }); } return true; }; } async getExistingTransactions(receiverWallet) { return new Promise(async (resolve, reject) => { let request = this.idb.open(this.dbName, 1); request.onerror = async (event) => await reject(event); request.onsuccess = async (event) => { const db = request.result; let tx = await db.transaction(this.storeName, "readonly"); request.onerror = (event) => reject(event); let store = tx.objectStore(this.storeName); let result = await store.get(receiverWallet); tx.oncomplete = async () => await resolve(result.result); }; }); } async getAllDataIndexedDb() { return new Promise(async (resolve, reject) => { let request = this.idb.open(this.dbName, 1); request.onerror = async (event) => { await reject(event); console.log("Db opening failed"); } request.onsuccess = async (event) => { console.log(event); const db = request.result; let tx = await db.transaction(this.storeName, "readonly"); request.onerror = (event) => reject(event); let store = tx.objectStore(this.storeName); let result = await store.getAll(); // console.log(result, "RESULT"); tx.oncomplete = async () => await resolve(result); }; }); } async addItemToDb(itemObj) { const dbPromise = this.idb.open(this.dbName, 1); dbPromise.onsuccess = () => { const db = dbPromise.result; var tx = db.transaction(this.storeName, "readwrite"); var userData = tx.objectStore(this.storeName); const users = userData.put(itemObj); users.onsuccess = (query) => { tx.oncomplete = function () { db.close(); }; }; }; } } exports.default = PeerToPeerWallet;