UNPKG

ptokens-deposit-address

Version:

repo holding the code related to deposit addresses

195 lines (192 loc) 5.8 kB
import Web3PromiEvent from 'web3-core-promievent'; import BigNumber from 'bignumber.js'; import { networks, crypto, script, opcodes, payments } from 'bitcoinjs-lib'; import * as utils from 'ptokens-utils'; import { eth, converters, helpers, constants } from 'ptokens-utils'; const HOST_NODE_POLLING_TIME_INTERVAL = 3000; const POLLING_TIME = 3000; const confirmations = { btc: 1, ltc: 4, doge: 1, rvn: 25 }; const hostBlockchainEvents = { ethereum: 'onEthTxConfirmed', eosio: 'onEosTxConfirmed' }; networks.litecoin = { messagePrefix: '\x19Litecoin Signed Message:\n', bech32: 'ltc', bip32: { public: 0x019da462, private: 0x019d9cfe }, pubKeyHash: 0x30, scriptHash: 0x32, wif: 0xb0 }; networks.litecoinTestnet = { messagePrefix: '\x19Litecoin Signed Message:\n', bech32: 'ltc', bip32: { public: 0x019da462, private: 0x019d9cfe }, pubKeyHash: 0x6f, scriptHash: 0x3a, wif: 0xb0 }; networks.dogecoin = { messagePrefix: '\x1aRavencoin Signed Message:\n', bip32: { public: 0x02facafd, private: 0x02fac398 }, pubKeyHash: 0x1e, scriptHash: 0x16, wif: 0x9e }; networks.ravencoin = { messagePrefix: '\x1aRavencoin Signed Message:\n', bip32: { public: 0x0488b21e, private: 0x0488ade4 }, pubKeyHash: 0x3c, scriptHash: 0x7a, wif: 0x80 }; networks.lbc = { pubKeyHash: 0x55, scriptHash: 0x7a }; const { constants: { networks: { BitcoinMainnet, BitcoinTestnet, LitecoinMainnet, LitecoinTestnet, DogecoinMainnet, RavencoinMainnet, LbryMainnet }, blockchains: { Bitcoin, Litecoin, Dogecoin, Ravencoin, Lbry } } } = utils; const NETWORKS = { [Bitcoin]: { [BitcoinMainnet]: networks.bitcoin, [BitcoinTestnet]: networks.testnet }, [Litecoin]: { [LitecoinMainnet]: networks.litecoin, [LitecoinTestnet]: networks.litecoinTestnet }, [Dogecoin]: { [DogecoinMainnet]: networks.dogecoin }, [Ravencoin]: { [RavencoinMainnet]: networks.ravencoin }, [Lbry]: { [LbryMainnet]: networks.lbc } }; class DepositAddress { constructor(_configs) { const { nativeBlockchain, nativeNetwork, hostBlockchain, hostNetwork, hostApi, node } = _configs; this.hostBlockchain = hostBlockchain; this.hostNetwork = hostNetwork; this.nativeBlockchain = nativeBlockchain; this.nativeNetwork = nativeNetwork; this.node = node; this.hostApi = hostApi; } async generate(_hostAddress) { try { const { nonce, enclavePublicKey, nativeDepositAddress } = await this.node.getNativeDepositAddress(_hostAddress); this.nonce = nonce; this.enclavePublicKey = enclavePublicKey; this.value = nativeDepositAddress; this.hostAddress = _hostAddress; return this.value; } catch (_err) { throw new Error('Error during deposit address generation'); } } toString() { return this.value; } verify() { const { constants: { blockchains: { Eosio, Telos } } } = utils; const network = NETWORKS[this.nativeBlockchain][this.nativeNetwork]; if (!network) throw new Error('Please use a valid combination of nativeNetwork and nativeBlockchain'); const hostAddressBuf = this.hostBlockchain === Eosio || this.hostBlockchain === Telos ? Buffer.from(this.hostAddress, 'utf-8') : Buffer.from(eth.removeHexPrefix(this.hostAddress), 'hex'); const nonceBuf = converters.encodeUint64le(this.nonce); const enclavePublicKeyBuf = Buffer.from(eth.removeHexPrefix(this.enclavePublicKey), 'hex'); const hostAddressAndNonceHashBuf = crypto.hash256(Buffer.concat([hostAddressBuf, nonceBuf])); const output = script.compile([].concat(hostAddressAndNonceHashBuf, opcodes.OP_DROP, enclavePublicKeyBuf, opcodes.OP_CHECKSIG)); const p2sh = payments.p2sh({ redeem: { output, network }, network }); return p2sh.address === this.value; } waitForDeposit() { const promiEvent = Web3PromiEvent(); const start = async () => { if (!this.hostApi) { promiEvent.reject('Provider not specified. Impossible to monitor the tx'); return; } if (!this.value) promiEvent.reject('Please generate a deposit address'); const shortNativeBlockchain = helpers.getBlockchainShortType(this.nativeBlockchain); const shortHostBlockchain = helpers.getBlockchainShortType(this.hostBlockchain); const nativeTxId = await utils[shortNativeBlockchain].monitorUtxoByAddress(this.nativeNetwork, this.value, promiEvent.eventEmitter, POLLING_TIME, 'nativeTxBroadcasted', 'nativeTxConfirmed', confirmations[shortNativeBlockchain]); const broadcastedHostTxReport = await this.node.monitorIncomingTransaction(nativeTxId, promiEvent.eventEmitter); const hostTxReceipt = await utils[shortHostBlockchain === 'bsc' || shortHostBlockchain === 'polygon' || shortHostBlockchain === 'arbitrum' ? 'eth' : shortHostBlockchain].waitForTransactionConfirmation(this.hostApi, broadcastedHostTxReport.broadcast_tx_hash, HOST_NODE_POLLING_TIME_INTERVAL); if (this.hostBlockchain !== constants.blockchains.Telos) { promiEvent.eventEmitter.emit(hostBlockchainEvents[this.hostBlockchain], hostTxReceipt); } promiEvent.eventEmitter.emit('hostTxConfirmed', hostTxReceipt); promiEvent.resolve({ amount: eth.offChainFormat(new BigNumber(broadcastedHostTxReport.host_tx_amount), 8).toFixed(), nativeTx: nativeTxId, hostTx: broadcastedHostTxReport.broadcast_tx_hash, to: this.hostAddress }); }; start(); return promiEvent.eventEmitter; } } export { DepositAddress };