Skip to content

Commit 6acc505

Browse files
committed
feat: rsk integration
1 parent b7c6409 commit 6acc505

File tree

37 files changed

+269
-19
lines changed

37 files changed

+269
-19
lines changed

packages/bitcore-node/src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const Config = function(): ConfigType {
6262
dbPass: process.env.DB_PASS || '',
6363
numWorkers: cpus().length,
6464
chains: {},
65-
modules: ['./bitcoin', './bitcoin-cash', './ethereum'],
65+
modules: ['./bitcoin', './bitcoin-cash', './ethereum', './rsk'],
6666
services: {
6767
api: {
6868
rateLimiter: {

packages/bitcore-node/src/modules/ethereum/api/csp.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export class ETHStateProvider extends InternalStateProvider implements IChainSta
8989
}
9090

9191
async getERC20TokenInfo(network: string, tokenAddress: string) {
92-
const token = await ETH.erc20For(network, tokenAddress);
92+
const token = await this.erc20For(network, tokenAddress); // Use `this` rather than ETH to make it generic for other EVM compatible chains to facilitate the class based inheritance of ETHStateProvider
9393
const [name, decimals, symbol] = await Promise.all([
9494
token.methods.name().call(),
9595
token.methods.decimals().call(),
@@ -360,7 +360,7 @@ export class ETHStateProvider extends InternalStateProvider implements IChainSta
360360
async streamWalletTransactions(params: StreamWalletTransactionsParams) {
361361
const { network, wallet, res, args } = params;
362362
const { web3 } = await this.getWeb3(network);
363-
const query = ETH.getWalletTransactionQuery(params);
363+
const query = this.getWalletTransactionQuery(params); // Use this rather than ETH to make it generic for other EVM compatible chains to facilitate the class based inheritance of ETHStateProvider
364364

365365
let transactionStream = new Readable({ objectMode: true });
366366
const walletAddresses = (await this.getWalletAddresses(wallet._id!)).map(waddres => waddres.address);
@@ -572,5 +572,11 @@ export class ETHStateProvider extends InternalStateProvider implements IChainSta
572572
};
573573
}
574574
}
575-
576-
export const ETH = new ETHStateProvider();
575+
/*
576+
*
577+
* Use the ETH implementation for RSK by inheriting the ETHStateProvider class rather than making its clone
578+
* This will reduce lot of maintenance cost and avoid code duplication
579+
* For other EVM compatible chains like RSK below export needs to be like new ETHStateProvider('RSK')
580+
* It's just a suggestion to use process.env.chain evn variable untill bitpay team can make it more generic for other EVM like chains
581+
*/
582+
export const ETH = new ETHStateProvider(process.env.chain || 'ETH');

packages/bitcore-node/src/modules/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class ModuleManager extends BaseModule {
5353
BCH: './bitcoin-cash',
5454
DOGE: './dogecoin',
5555
LTC: './litecoin',
56-
XRP: './ripple'
56+
XRP: './ripple',
57+
RSK: './rsk'
5758
};
5859

5960
loadConfigured() {

packages/bitcore-node/src/modules/modules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The modules in this table will automatically register with `bitcore-node` if you
1212
| LTC | litecoin | ./litecoin |
1313
| DOGE | dogecoin | ./dogecoin |
1414
| XRP | ripple | ./ripple |
15+
| RSK | rsk | ./rsk |
1516

1617
If there is a custom or third-party module you'd like to use, follow the example below.
1718

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Config from '../../../config';
2+
import { ETHStateProvider } from '../../ethereum/api/csp';
3+
4+
export { EventLog } from '../../ethereum/api/csp';
5+
export class RSKStateProvider extends ETHStateProvider {
6+
/*
7+
* Reusing ETHStateProvider class for RSK
8+
* Purpose is to avoid code duplication and reduce maintenance cost
9+
*/
10+
constructor(public chain: string = 'RSK') {
11+
super(chain);
12+
this.config = Config.chains[this.chain];
13+
}
14+
15+
}
16+
17+
export const RSK = new RSKStateProvider();
18+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Router } from 'express';
2+
import logger from '../../../logger';
3+
import { RSK } from './csp';
4+
export const RskRoutes = Router();
5+
6+
RskRoutes.get('/api/RSK/:network/address/:address/txs/count', async (req, res) => {
7+
let { address, network } = req.params;
8+
try {
9+
const nonce = await RSK.getAccountNonce(network, address);
10+
res.json({ nonce });
11+
} catch (err) {
12+
logger.error('Nonce Error::' + err);
13+
res.status(500).send(err);
14+
}
15+
});
16+
17+
RskRoutes.post('/api/RSK/:network/gas', async (req, res) => {
18+
const { from, to, value, data, gasPrice } = req.body;
19+
const { network } = req.params;
20+
try {
21+
const gasLimit = await RSK.estimateGas({ network, from, to, value, data, gasPrice });
22+
res.json(gasLimit);
23+
} catch (err) {
24+
res.status(500).send(err);
25+
}
26+
});
27+
28+
RskRoutes.get('/api/RSK/:network/token/:tokenAddress', async (req, res) => {
29+
const { network, tokenAddress } = req.params;
30+
try {
31+
const tokenInfo = await RSK.getERC20TokenInfo(network, tokenAddress);
32+
res.json(tokenInfo);
33+
} catch (err) {
34+
res.status(500).send(err);
35+
}
36+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { BaseModule } from '..';
2+
import { RSKStateProvider } from './api/csp';
3+
import { RskRoutes } from './api/rsk-routes';
4+
import { RskP2pWorker } from './p2p/p2p';
5+
import { RskVerificationPeer } from './p2p/RskVerificationPeer';
6+
7+
export default class RSKModule extends BaseModule {
8+
constructor(services: BaseModule['bitcoreServices']) {
9+
super(services);
10+
services.P2P.register('RSK', RskP2pWorker);
11+
services.CSP.registerService('RSK', new RSKStateProvider('RSK'));
12+
services.Api.app.use(RskRoutes);
13+
services.Verification.register('RSK', RskVerificationPeer);
14+
}
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { EthVerificationPeer } from '../../ethereum/p2p/EthVerificationPeer';
2+
3+
export class RskVerificationPeer extends EthVerificationPeer {
4+
/*
5+
* Reusing EthVerificationPeer class for RSK
6+
* Purpose is to avoid code duplication and reduce maintenance cost
7+
*/
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { EthP2pWorker } from '../../ethereum/p2p/p2p';
2+
import { EthBlockStorage } from '../../ethereum/models/block';
3+
export class RskP2pWorker extends EthP2pWorker {
4+
/*
5+
* Reusing EthP2pWorker class for RSK
6+
* Purpose is to avoid code duplication and reduce maintenance cost
7+
*/
8+
constructor({ chain, network, chainConfig, blockModel = EthBlockStorage}) {
9+
super({ chain, network, chainConfig, blockModel });
10+
this.chain = 'RSK';
11+
}
12+
}

packages/bitcore-wallet-client/src/lib/api.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2964,7 +2964,9 @@ export class API extends EventEmitter {
29642964
['btc', 'livenet', true],
29652965
['bch', 'livenet', true],
29662966
['doge', 'livenet', true],
2967-
['ltc', 'livenet', true]
2967+
['ltc', 'livenet', true],
2968+
['rsk', 'livenet'],
2969+
['rbtc', 'livenet'],
29682970
];
29692971
if (key.use44forMultisig) {
29702972
// testing old multi sig

0 commit comments

Comments
 (0)