@ravenrebels/ravencoin-jswallet
Version:
Ravencoin JavaScript wallet library
1 lines • 23.5 kB
Source Map (JSON)
{"mappings":"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","sources":["src/src/Types.ts","src/src/Errors.ts","src/src/utils.ts","src/src/blockchain/SendManyTransaction.ts","src/src/blockchain/sweep.ts","src/src/blockchain/Transaction.ts","src/src/getBaseCurrencyByNetwork.ts","src/src/contants.ts","src/src/getBalance.ts","src/src/getAssets.ts","src/src/ravencoinWallet.ts","src/ravencoinWallet.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,"import { getRPC, methods } from \"@ravenrebels/ravencoin-rpc\";\nimport RavencoinKey from \"@ravenrebels/ravencoin-key\";\nimport Signer from \"@ravenrebels/ravencoin-sign-transaction\";\nimport {\n ChainType,\n IAddressDelta,\n IAddressMetaData,\n IMempoolEntry,\n IOptions,\n ISend,\n ISendManyOptions,\n ISendResult,\n IUTXO,\n SweepResult,\n} from \"./Types\";\n\nimport { sweep } from \"./blockchain/sweep\";\nimport { Transaction } from \"./blockchain/Transaction\";\nimport { SendManyTransaction } from \"./blockchain/SendManyTransaction\";\nimport { getBaseCurrencyByNetwork } from \"./getBaseCurrencyByNetwork\";\nimport { getBalance } from \"./getBalance\";\nimport { ValidationError } from \"./Errors\";\nimport { getAssets } from \"./getAssets\";\n\nexport { Transaction };\nexport { SendManyTransaction };\nconst URL_RAVENCOIN_MAINNET = \"https://rvn-rpc-mainnet.ting.finance/rpc\";\nconst URL_RAVENCOIN_TESTNET = \"https://rvn-rpc-testnet.ting.finance/rpc\";\nconst URL_EVRMORE_MAINNET = \"https://evr-rpc-mainnet.ting.finance/rpc\";\n\n//Avoid singleton (anti-pattern)\n//Meaning multiple instances of the wallet must be able to co-exist\n\nexport class Wallet {\n rpc = getRPC(\"anonymous\", \"anonymous\", URL_RAVENCOIN_MAINNET);\n _mnemonic = \"\";\n network: ChainType = \"rvn\";\n addressObjects: Array<IAddressMetaData> = [];\n receiveAddress = \"\";\n changeAddress = \"\";\n addressPosition = 0;\n baseCurrency = \"RVN\"; //Default is RVN but it could be EVR\n offlineMode = false;\n setBaseCurrency(currency: string) {\n this.baseCurrency = currency;\n }\n getBaseCurrency() {\n return this.baseCurrency;\n }\n /**\n * Sweeping a private key means to send all the funds the address holds to your your wallet.\n * The private key you sweep does not become a part of your wallet.\n *\n * NOTE: the address you sweep needs to cointain enough RVN to pay for the transaction\n *\n * @param WIF the private key of the address that you want move funds from\n * @returns either a string, that is the transaction id or null if there were no funds to send\n */\n sweep(WIF: string, onlineMode: boolean): Promise<SweepResult> {\n const wallet = this;\n\n return sweep(WIF, wallet, onlineMode);\n }\n getAddressObjects() {\n return this.addressObjects;\n }\n getAddresses(): Array<string> {\n const addresses = this.addressObjects.map((obj) => {\n return obj.address;\n });\n return addresses;\n }\n\n async init(options: IOptions) {\n let username = \"anonymous\";\n let password = \"anonymous\";\n let url = URL_RAVENCOIN_MAINNET;\n\n //VALIDATION\n if (!options) {\n throw Error(\"option argument is mandatory\");\n }\n\n if (options.offlineMode === true) {\n this.offlineMode = true;\n }\n if (!options.mnemonic) {\n throw Error(\"option.mnemonic is mandatory\");\n }\n if (options.network === \"rvn-test\") {\n url = URL_RAVENCOIN_TESTNET;\n }\n if (options.network === \"evr\") {\n url = URL_EVRMORE_MAINNET;\n }\n url = options.rpc_url || url;\n password = options.rpc_password || password;\n username = options.rpc_username || username;\n\n if (options.network) {\n this.network = options.network;\n this.setBaseCurrency(getBaseCurrencyByNetwork(options.network));\n }\n\n this.rpc = getRPC(username, password, url);\n this._mnemonic = options.mnemonic;\n\n //Generating the hd key is slow, so we re-use the object\n const hdKey = RavencoinKey.getHDKey(this.network, this._mnemonic);\n const coinType = RavencoinKey.getCoinType(this.network);\n const ACCOUNT = 0;\n\n const minAmountOfAddresses = Number.isFinite(options.minAmountOfAddresses)\n ? options.minAmountOfAddresses\n : 0;\n\n let doneDerivingAddresses = false;\n while (doneDerivingAddresses === false) {\n //We add new addresses to tempAddresses so we can check history for the last 20\n const tempAddresses = [] as string[];\n\n for (let i = 0; i < 20; i++) {\n const external = RavencoinKey.getAddressByPath(\n this.network,\n hdKey,\n `m/44'/${coinType}'/${ACCOUNT}'/0/${this.addressPosition}`\n );\n\n const internal = RavencoinKey.getAddressByPath(\n this.network,\n hdKey,\n `m/44'/${coinType}'/${ACCOUNT}'/1/${this.addressPosition}`\n );\n\n this.addressObjects.push(external);\n this.addressObjects.push(internal);\n this.addressPosition++;\n\n tempAddresses.push(external.address + \"\");\n tempAddresses.push(internal.address + \"\");\n }\n\n if (\n minAmountOfAddresses &&\n minAmountOfAddresses >= this.addressPosition\n ) {\n //In case we intend to create extra addresses on startup\n doneDerivingAddresses = false;\n } else if (this.offlineMode === true) {\n //BREAK generation of addresses and do NOT check history on the network\n doneDerivingAddresses = true;\n } else {\n //If no history, break\n doneDerivingAddresses =\n false === (await this.hasHistory(tempAddresses));\n }\n }\n }\n async hasHistory(addresses: Array<string>): Promise<boolean> {\n const includeAssets = true;\n const obj = {\n addresses,\n };\n\n const asdf = (await this.rpc(methods.getaddressbalance, [\n obj,\n includeAssets,\n ])) as any;\n\n //@ts-ignore\n const hasReceived = Object.values(asdf).find((asset) => asset.received > 0);\n\n return !!hasReceived;\n }\n\n async _getFirstUnusedAddress(external: boolean) {\n //First, check if lastReceivedAddress\n if (external === true && this.receiveAddress) {\n const asdf = await this.hasHistory([this.receiveAddress]);\n if (asdf === false) {\n return this.receiveAddress;\n }\n }\n if (external === false && this.changeAddress) {\n const asdf = await this.hasHistory([this.changeAddress]);\n if (asdf === false) {\n return this.changeAddress;\n }\n }\n\n //First make a list of relevant addresses, either external (even) or change (odd)\n const addresses: string[] = [];\n\n this.getAddresses().map(function (address: string, index: number) {\n if (external === true && index % 2 === 0) {\n addresses.push(address);\n } else if (external === false && index % 2 !== 0) {\n addresses.push(address);\n }\n });\n\n //Use BINARY SEARCH\n\n // Binary search implementation to find the first item with `history` set to false\n const binarySearch = async (_addresses: string[]) => {\n let low = 0;\n let high = _addresses.length - 1;\n let result = \"\";\n\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const addy = _addresses[mid];\n\n const hasHistory = await this.hasHistory([addy]);\n if (hasHistory === false) {\n result = addy;\n high = mid - 1; // Continue searching towards the left\n } else {\n low = mid + 1; // Continue searching towards the right\n }\n }\n\n return result;\n };\n\n const result = await binarySearch(addresses);\n\n if (!result) {\n //IF we have not found one, return the first address\n return addresses[0];\n }\n if (external === true) {\n this.receiveAddress = result;\n } else {\n this.changeAddress = result;\n }\n\n return result;\n }\n\n async getHistory(): Promise<IAddressDelta[]> {\n const assetName = \"\"; //Must be empty string, NOT \"*\"\n const addresses = this.getAddresses();\n const deltas = this.rpc(methods.getaddressdeltas, [\n { addresses, assetName },\n ]);\n //@ts-ignore\n const addressDeltas: IAddressDelta[] = deltas as IAddressDelta[];\n return addressDeltas;\n }\n async getMempool(): Promise<IMempoolEntry[]> {\n const method = methods.getaddressmempool;\n const includeAssets = true;\n const params = [{ addresses: this.getAddresses() }, includeAssets];\n return this.rpc(method, params) as Promise<IMempoolEntry[]>;\n }\n async getReceiveAddress() {\n const isExternal = true;\n return this._getFirstUnusedAddress(isExternal);\n }\n\n async getChangeAddress() {\n const isExternal = false;\n return this._getFirstUnusedAddress(isExternal);\n }\n /**\n *\n * @param assetName if present, only return UTXOs for that asset, otherwise for all assets\n * @returns UTXOs for assets\n */\n async getAssetUTXOs(assetName?: string): Promise<IUTXO[]> {\n //If no asset name, set to wildcard, meaning all assets\n const _assetName = !assetName ? \"*\" : assetName;\n const chainInfo = false;\n const params = [\n { addresses: this.getAddresses(), chainInfo, assetName: _assetName },\n ];\n\n return this.rpc(methods.getaddressutxos, params);\n }\n async getUTXOs() {\n return this.rpc(methods.getaddressutxos, [\n { addresses: this.getAddresses() },\n ]);\n }\n\n getPrivateKeyByAddress(address: string) {\n const f = this.addressObjects.find((a) => a.address === address);\n\n if (!f) {\n return undefined;\n }\n return f.WIF;\n }\n async sendRawTransaction(raw: string): Promise<string> {\n return this.rpc(\"sendrawtransaction\", [raw]);\n }\n\n async send(options: ISend): Promise<ISendResult> {\n //ACTUAL SENDING TRANSACTION\n\n //Important, do not swallow the exceptions/errors of createTransaction, let them fly\n const sendResult: ISendResult = await this.createTransaction(options);\n\n const id = await this.rpc(\"sendrawtransaction\", [\n sendResult.debug.signedTransaction,\n ]);\n sendResult.transactionId = id;\n\n return sendResult;\n }\n\n async sendMany({ outputs, assetName }: ISendManyOptions) {\n const options = {\n wallet: this,\n outputs,\n assetName,\n };\n const sendResult: ISendResult = await this.createSendManyTransaction(\n options\n );\n\n //ACTUAL SENDING TRANSACTION\n //Important, do not swallow the exceptions/errors of createSendManyTransaction, let them fly\n\n try {\n const id = await this.rpc(\"sendrawtransaction\", [\n sendResult.debug.signedTransaction,\n ]);\n sendResult.transactionId = id;\n\n return sendResult;\n } catch (e) {\n throw new Error(\n \"Error while sending, perhaps you have pending transaction? Please try again.\"\n );\n }\n }\n /**\n * Does all the heavy lifting regarding creating a SendManyTransaction\n * but it does not broadcast the actual transaction.\n * Perhaps the user wants to accept the transaction fee?\n * @param options\n * @returns An transaction that has not been broadcasted\n */\n async createTransaction(options: ISend): Promise<ISendResult> {\n const { amount, toAddress } = options;\n let { assetName } = options;\n\n if (!assetName) {\n assetName = this.baseCurrency;\n }\n\n //Validation\n if (!toAddress) {\n throw Error(\"Wallet.send toAddress is mandatory\");\n }\n if (!amount) {\n throw Error(\"Wallet.send amount is mandatory\");\n }\n const changeAddress = await this.getChangeAddress();\n\n if (changeAddress === toAddress) {\n throw new Error(\"Change address cannot be the same as toAddress\");\n }\n const transaction = new Transaction({\n assetName,\n amount,\n toAddress,\n wallet: this,\n /* optional */\n forcedChangeAddressAssets: options.forcedChangeAddressAssets,\n forcedUTXOs: options.forcedUTXOs,\n forcedChangeAddressBaseCurrency: options.forcedChangeAddressBaseCurrency,\n });\n\n await transaction.loadData();\n\n const inputs = transaction.getInputs();\n const outputs = await transaction.getOutputs();\n\n const privateKeys = transaction.getPrivateKeys();\n\n const raw = await this.rpc(\"createrawtransaction\", [inputs, outputs]);\n const signed = Signer.sign(\n this.network,\n raw,\n transaction.getUTXOs(),\n privateKeys\n );\n\n try {\n // const id = await this.rpc(\"sendrawtransaction\", [signed]);\n const sendResult: ISendResult = {\n transactionId: null,\n debug: {\n amount,\n assetName,\n fee: transaction.getFee(),\n inputs,\n outputs,\n privateKeys,\n rawUnsignedTransaction: raw,\n rvnChangeAmount: transaction.getBaseCurrencyChange(),\n rvnAmount: transaction.getBaseCurrencyAmount(),\n signedTransaction: signed,\n UTXOs: transaction.getUTXOs(),\n walletMempool: transaction.getWalletMempool(),\n },\n };\n return sendResult;\n } catch (e) {\n throw new Error(\n \"Error while sending, perhaps you have pending transaction? Please try again.\"\n );\n }\n }\n\n /**\n * Does all the heavy lifting regarding creating a transaction\n * but it does not broadcast the actual transaction.\n * Perhaps the user wants to accept the transaction fee?\n * @param options\n * @returns An transaction that has not been broadcasted\n */\n async createSendManyTransaction(options: {\n assetName?: string;\n outputs: { [key: string]: number };\n }): Promise<ISendResult> {\n let { assetName } = options;\n\n if (!assetName) {\n assetName = this.baseCurrency;\n }\n\n //Validation\n if (!options.outputs) {\n throw Error(\"Wallet.createSendManyTransaction outputs is mandatory\");\n } else if (Object.keys(options.outputs).length === 0) {\n throw new ValidationError(\n \"outputs is mandatory, shoud be an object with address as keys and amounts (numbers) as values\"\n );\n }\n const changeAddress = await this.getChangeAddress();\n\n const toAddresses = Object.keys(options.outputs);\n if (toAddresses.includes(changeAddress)) {\n throw new Error(\"You cannot send to your current change address\");\n }\n const transaction = new SendManyTransaction({\n assetName,\n outputs: options.outputs,\n wallet: this,\n });\n\n await transaction.loadData();\n\n const inputs = transaction.getInputs();\n const outputs = await transaction.getOutputs();\n\n const privateKeys = transaction.getPrivateKeys();\n\n const raw = await this.rpc(\"createrawtransaction\", [inputs, outputs]);\n const signed = Signer.sign(\n this.network,\n raw,\n transaction.getUTXOs(),\n privateKeys\n );\n\n try {\n const sendResult: ISendResult = {\n transactionId: null,\n debug: {\n amount: transaction.getAmount(),\n assetName,\n fee: transaction.getFee(),\n inputs,\n outputs,\n privateKeys,\n rawUnsignedTransaction: raw,\n rvnChangeAmount: transaction.getBaseCurrencyChange(),\n rvnAmount: transaction.getBaseCurrencyAmount(),\n signedTransaction: signed,\n UTXOs: transaction.getUTXOs(),\n walletMempool: transaction.getWalletMempool(),\n },\n };\n return sendResult;\n } catch (e) {\n throw new Error(\n \"Error while sending, perhaps you have pending transaction? Please try again.\"\n );\n }\n }\n\n /**\n * This method checks if an UTXO is being spent in the mempool.\n * rpc getaddressutxos will list available UTXOs on the chain.\n * BUT an UTXO can be being spent by a transaction in mempool.\n *\n * @param utxo\n * @returns boolean true if utxo is being spent in mempool, false if not\n */\n async isSpentInMempool(utxo: IUTXO) {\n const details = await this.rpc(\"gettxout\", [utxo.txid, utxo.outputIndex]);\n return details === null;\n }\n async getAssets() {\n return getAssets(this, this.getAddresses());\n }\n async getBalance() {\n const a = this.getAddresses();\n return getBalance(this, a);\n }\n async convertMempoolEntryToUTXO(mempoolEntry: IMempoolEntry): Promise<IUTXO> {\n //Mempool items might not have the script attbribute, we need it\n const out = await this.rpc(\"gettxout\", [\n mempoolEntry.txid,\n mempoolEntry.index,\n true,\n ]);\n\n const utxo = {\n ...mempoolEntry,\n script: out.scriptPubKey.hex,\n outputIndex: mempoolEntry.index,\n value: mempoolEntry.satoshis / 1e8,\n };\n return utxo;\n }\n\n /**\n * Get list of spendable UTXOs in mempool.\n * Note: a UTXO in mempool can already be \"being spent\"\n * @param mempool (optional)\n * @returns list of UTXOs in mempool ready to spend\n */\n async getUTXOsInMempool(mempool?: IMempoolEntry[]) {\n //If no mempool argument, fetch mempool\n let _mempool = mempool;\n if (!_mempool) {\n const m = await this.getMempool();\n _mempool = m;\n }\n const mySet = new Set();\n for (let item of _mempool) {\n if (!item.prevtxid) {\n continue;\n }\n const value = item.prevtxid + \"_\" + item.prevout;\n mySet.add(value);\n }\n\n const spendable = _mempool.filter((item) => {\n if (item.satoshis < 0) {\n return false;\n }\n const value = item.txid + \"_\" + item.index;\n return mySet.has(value) === false;\n });\n\n const utxos: IUTXO[] = [];\n\n for (let s of spendable) {\n const u = await this.convertMempoolEntryToUTXO(s);\n utxos.push(u);\n }\n return utxos;\n }\n}\n\nexport default {\n createInstance,\n getBaseCurrencyByNetwork,\n};\nexport async function createInstance(options: IOptions): Promise<Wallet> {\n const wallet = new Wallet();\n await wallet.init(options);\n return wallet;\n}\n"],"names":[],"version":3,"file":"types.d.ts.map"}