Skip to content

Commit

Permalink
feat(ptokens-pbep20 & ptokens & ptokens-utils): adds support for bep2…
Browse files Browse the repository at this point in the history
…0 tokens and adds ocp on eth
  • Loading branch information
allemanfredi committed Apr 29, 2021
1 parent e0c4f3e commit 3035132
Show file tree
Hide file tree
Showing 20 changed files with 648 additions and 11 deletions.
54 changes: 54 additions & 0 deletions packages/ptokens-pbep20/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# ptokens-pbep20

It allows to easily convert any BEP20 tokens on the Binance Smart Chain blockchain into their pTokenized equivalents on the another blockchain.

 

***

 

### Installation:

```
npm install ptokens-pbep20
```

 

***

 

### Usage:

```js
import { pBEP20 } from 'ptokens-pbep20'
import { HttpProvider } from 'ptokens-providers'
import { Node } from 'ptokens-node'

const pbep20 = new pBEP20({
blockchain: 'ETH',
network: 'testnet', // 'testnet' or 'mainnet', default 'testnet'

// if you want to be more detailed
hostBlockchain: 'ETH',
hostNetwork: 'mainnet',
nativeBlockchain: 'BSC'
nativeNetwork: 'mainnet'

ethPrivateKey: 'Eth private key',
ethProvider: 'Eth provider', // or instance of Web3 provider
defaultNode: new Node({
pToken: 'OCP',
blockchain: 'ETH',
provider: new HttpProvider(
'node endpoint',
{
'Access-Control-Allow-Origin': '*',
...
}
)
})
})
```
3 changes: 3 additions & 0 deletions packages/ptokens-pbep20/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const jestConfig = require('../../jest.config')

module.exports = jestConfig()
46 changes: 46 additions & 0 deletions packages/ptokens-pbep20/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "ptokens-pbep20",
"version": "0.10.0",
"description": "repo holding the code for interacting with a BEP20 token",
"repository": "https://github.com/provable-things/ptokens.js/tree/master/packages/ptokens-pbep20",
"main": "dist/ptokens-pbep20.cjs.js",
"module": "dist/ptokens-pbep20.esm.js",
"browser": "dist/ptokens-pbep20.umd.js",
"types": "types/index.d.ts",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"test": "jest --ci --forceExit --detectOpenHandles",
"lint": "npx eslint ./src --fix && npx eslint ./tests --fix",
"dtslint": "dtslint types --onlyTestTsNext"
},
"keywords": [
"ptokens",
"javaScript",
"ethereum",
"eos",
"pnetwork"
],
"author": "alle.manfredi@gmail.com @provable-things",
"license": "LGPL-3.0",
"dependencies": {
"@babel/runtime": "^7.3.1",
"@types/node": "^12.6.1",
"bignumber.js": "^9.0.0",
"chai": "^4.2.0",
"ptokens-node": "^0.10.0",
"ptokens-node-selector": "^0.10.0",
"ptokens-utils": "^0.10.0",
"web3": "^1.2.2",
"web3-core-promievent": "^1.2.1",
"web3-utils": "^1.2.4"
},
"devDependencies": {
"dtslint": "0.4.2",
"jest": "^24.8.0"
},
"files": [
"dist",
"types/index.d.ts"
]
}
8 changes: 8 additions & 0 deletions packages/ptokens-pbep20/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import pkg from './package.json'
import rollupConfig from '../../rollup.config'

export default rollupConfig('pBEP20', pkg.name, {
'ptokens-node-selector': 'ptokens-node-selector',
'ptokens-node': 'ptokens-node',
'ptokens-utils': 'ptokens-utils'
})
209 changes: 209 additions & 0 deletions packages/ptokens-pbep20/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import Web3 from 'web3'
import Web3PromiEvent from 'web3-core-promievent'
import { NodeSelector } from 'ptokens-node-selector'
import { abi, constants, eth, helpers, redeemFrom } from 'ptokens-utils'
import BigNumber from 'bignumber.js'
import Web3Utils from 'web3-utils'
import minimumAmounts from './minimum-amounts'

export class pBEP20 extends NodeSelector {
constructor(_configs) {
const { hostBlockchain, hostNetwork, nativeBlockchain, nativeNetwork } = helpers.parseParams(
_configs,
constants.blockchains.BinanceSmartChain
)

super({
pToken: _configs.pToken,
hostBlockchain,
hostNetwork,
nativeBlockchain,
nativeNetwork,
defaultNode: _configs.defaultNode
})

const { bscPrivateKey, bscProvider, ethPrivateKey, ethProvider } = _configs

if (bscProvider) this.web3 = new Web3(bscProvider)
if (bscPrivateKey) {
const account = this.web3.eth.accounts.privateKeyToAccount(eth.addHexPrefix(bscPrivateKey))
this.web3.eth.defaultAccount = account.address
this.bscPrivateKey = eth.addHexPrefix(bscPrivateKey)
} else {
this.bscPrivateKey = null
}

if (ethProvider) this.hostApi = new Web3(ethProvider)
if (ethPrivateKey) {
const account = this.hostApi.eth.accounts.privateKeyToAccount(eth.addHexPrefix(ethPrivateKey))
this.hostApi.eth.defaultAccount = account.address
this.hostPrivateKey = eth.addHexPrefix(ethPrivateKey)
} else {
this.hostPrivateKey = null
}
}
/**
* @param {String|BigNumber|BN} _amount in wei
* @param {String} _hostAccount
* @param {IssueOptions} _options
*/
issue(_amount, _hostAccount, _options = {}) {
const promiEvent = Web3PromiEvent()
const start = async () => {
try {
const { gas, gasPrice } = _options
const { blockchains } = constants
await this._loadData()

const minimumAmount = minimumAmounts[this.nativeContractAddress.toLowerCase()].issue
if (BigNumber(_amount).isLessThan(minimumAmount)) {
promiEvent.reject(`Impossible to issue less than ${minimumAmount}`)
return
}

if (this.hostBlockchain === blockchains.Ethereum && !Web3Utils.isAddress(_hostAccount)) {
promiEvent.reject('Invalid host account')
return
}

if (!this.selectedNode) await this.select()

let bscTxHash = null
const waitForEthTransaction = () =>
new Promise((_resolve, _reject) => {
eth[this.bscPrivateKey ? 'sendSignedMethodTx' : 'makeContractSend'](
this.web3,
'pegIn',
{
privateKey: this.bscPrivateKey,
abi: abi.pERC20Vault,
gas,
gasPrice,
contractAddress: eth.addHexPrefix(this.nativeVaultAddress),
value: 0
},
[_amount, this.nativeContractAddress, _hostAccount]
)
.once('transactionHash', _hash => {
bscTxHash = _hash
promiEvent.eventEmitter.emit('nativeTxBroadcasted', bscTxHash)
})
.once('receipt', _resolve)
.once('error', _reject)
})
const ethTxReceipt = await waitForEthTransaction()
promiEvent.eventEmitter.emit('nativeTxConfirmed', ethTxReceipt)

const incomingTxReport = await this.selectedNode.monitorIncomingTransaction(bscTxHash, promiEvent.eventEmitter)

let hostTxReceipt
if (this.hostBlockchain === blockchains.Ethereum)
hostTxReceipt = await eth.waitForTransactionConfirmation(this.hostApi, incomingTxReport.broadcast_tx_hash)

promiEvent.eventEmitter.emit('hostTxConfirmed', hostTxReceipt)
promiEvent.resolve({
to: _hostAccount,
nativeTx: bscTxHash,
hostTx: incomingTxReport.broadcast_tx_hash,
amount: BigNumber(_amount).toFixed()
})
} catch (_err) {
promiEvent.reject(_err)
}
}

start()
return promiEvent.eventEmitter
}

/**
*
* @param {string|number} _amount
* @param {string} _nativeAccount
* @param {Options} _options
*/
redeem(_amount, _nativeAccount, _options = {}) {
const promiEvent = Web3PromiEvent()

const start = async () => {
try {
const { gas, gasPrice } = _options
const { blockchains } = constants

await this._loadData()

const minimumAmount = minimumAmounts[this.nativeContractAddress.toLowerCase()].redeem[this.hostBlockchain]
if (BigNumber(_amount).isLessThan(minimumAmount)) {
promiEvent.reject(`Impossible to redeem less than ${minimumAmount}`)
return
}

if (this.nativeBlockchain === blockchains.Ethereum && !Web3Utils.isAddress(_nativeAccount)) {
promiEvent.reject('Invalid native account')
return
}

if (!this.selectedNode) await this.select()

const { redeemFromEvmCompatible } = redeemFrom

let hostTxHash
if (this.hostBlockchain === blockchains.Ethereum) {
const hostTxReceipt = await redeemFromEvmCompatible(
this.hostApi,
{
privateKey: this.hostPrivateKey,
gas,
gasPrice,
contractAddress: this.hostContractAddress,
value: 0
},
[_amount, _nativeAccount],
promiEvent,
'hostTxBroadcasted'
)

promiEvent.eventEmitter.emit('hostTxConfirmed', hostTxReceipt)
hostTxHash = hostTxReceipt.transactionHash
}

const incomingTxReport = await this.selectedNode.monitorIncomingTransaction(hostTxHash, promiEvent.eventEmitter)
const nativeTxReceipt = await eth.waitForTransactionConfirmation(
this.hostApi,
incomingTxReport.broadcast_tx_hash
)
promiEvent.eventEmitter.emit('nativeTxConfirmed', nativeTxReceipt)

promiEvent.resolve({
to: _nativeAccount,
nativeTx: nativeTxReceipt.transactionHash,
hostTx: hostTxHash,
amount: BigNumber(_amount).toFixed()
})
} catch (_err) {
promiEvent.reject(_err)
}
}

start()
return promiEvent.eventEmitter
}

async _loadData() {
try {
if (!this.selectedNode) await this.select()
if (!this.nativeContractAddress || !this.hostContractAddress) {
const {
native_smart_contract_address,
host_smart_contract_address,
native_vault_address
} = await this.selectedNode.getInfo()
this.nativeContractAddress = eth.addHexPrefix(native_smart_contract_address)
this.hostContractAddress = eth.addHexPrefix(host_smart_contract_address)
this.nativeVaultAddress = native_vault_address ? eth.addHexPrefix(native_vault_address) : null
}
} catch (_err) {
throw new Error(`Error during loading data: ${_err.message}`)
}
}
}
9 changes: 9 additions & 0 deletions packages/ptokens-pbep20/src/minimum-amounts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { constants } from 'ptokens-utils'
export default {
[constants.tokens['binance-smart-chain'].mainnet.OCP]: {
issue: 1000000000,
redeem: {
[constants.blockchains.Ethereum]: 0.000000001
}
}
}
Loading

0 comments on commit 3035132

Please sign in to comment.