ptokens-deposit-address
Version:
repo holding the code related to deposit addresses
195 lines (192 loc) • 5.8 kB
JavaScript
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 };