Skip to content

Commit

Permalink
ALL-3155 Add BNB support (#1003)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hathoriel authored Oct 26, 2023
1 parent 81b313d commit 4f7231b
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [4.1.17] - 2023.10.26
### Added
- Added RPC support for the BNB network. Users can now make RPC calls to these network using the `Network.BNB` network.

## [4.1.16] - 2023.10.24
### Added
- Added Beacon chain v1 support for the Ethereum
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tatumio/tatum",
"version": "4.1.16",
"version": "4.1.17",
"description": "Tatum JS SDK",
"author": "Tatum",
"repository": "https://github.com/tatumio/tatum-js",
Expand Down
6 changes: 5 additions & 1 deletion src/dto/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum Network {
AVALANCHE_P = 'avax-p-mainnet',
AVALANCHE_X = 'avax-x-mainnet',
BINANCE_SMART_CHAIN = 'bsc-mainnet',
BNB = 'bnb-beacon-chain-mainnet',
BITCOIN = 'bitcoin-mainnet',
BITCOIN_CASH = 'bitcoin-cash-mainnet',
CARDANO = 'cardano-mainnet',
Expand Down Expand Up @@ -235,6 +236,7 @@ export const EOS_LOAD_BALANCER_NETWORKS = [Network.EOS]
export const XRP_LOAD_BALANCER_NETWORKS = [Network.XRP, Network.XRP_TESTNET]
export const NATIVE_EVM_LOAD_BALANCER_NETWORKS = [Network.KLAYTN, Network.KLAYTN_BAOBAB]
export const SOLANA_NETWORKS = [Network.SOLANA, Network.SOLANA_DEVNET]
export const BNB_LOAD_BALANCER_NETWORKS = [Network.BNB]

export const LOAD_BALANCER_NETWORKS = [
...UTXO_LOAD_BALANCER_NETWORKS,
Expand All @@ -244,6 +246,7 @@ export const LOAD_BALANCER_NETWORKS = [
...XRP_LOAD_BALANCER_NETWORKS,
...NATIVE_EVM_LOAD_BALANCER_NETWORKS,
...SOLANA_NETWORKS,
...BNB_LOAD_BALANCER_NETWORKS,
]

export const EVM_ARCHIVE_NON_ARCHIVE_LOAD_BALANCER_NETWORKS = [
Expand Down Expand Up @@ -291,7 +294,6 @@ export const isEosNetwork = (network: Network) => EOS_NETWORKS.includes(network)

export const isLoadBalancerNetwork = (network: Network) => LOAD_BALANCER_NETWORKS.includes(network)


export const isEvmLoadBalancerNetwork = (network: Network) => EVM_LOAD_BALANCER_NETWORKS.includes(network)

export const isEvmArchiveNonArchiveLoadBalancerNetwork = (network: Network) =>
Expand All @@ -309,6 +311,8 @@ export const isXrpLoadBalancerNetwork = (network: Network) => XRP_LOAD_BALANCER_
export const isNativeEvmLoadBalancerNetwork = (network: Network) =>
NATIVE_EVM_LOAD_BALANCER_NETWORKS.includes(network)

export const isBnbLoadBalancerNetwork = (network: Network) => BNB_LOAD_BALANCER_NETWORKS.includes(network)

export const isSameGetBlockNetwork = (network: Network) =>
isUtxoBasedNetwork(network) ||
isEvmBasedNetwork(network) ||
Expand Down
69 changes: 69 additions & 0 deletions src/dto/rpc/BnbRpcSuite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { JsonRpcResponse } from '../JsonRpcResponse.dto'

export interface Height {
height: string
}

export interface AbciQuery {
path: string,
data: string
height?: string
prove?: boolean
}

export interface Validators {
height?: string
page?: string
perPage?: string
}

export interface Tx { hash: string, prove?: boolean }

export interface TxSearch { query: string, prove?: boolean, page?: string }

export interface Broadcast { tx: string }

export interface Blockchain { minHeight?: string, maxHeight?: string }

export interface UnconfirmedTxs { limit?: string }

export interface BnbRpcInterface {
status(): Promise<JsonRpcResponse<any>>
abciInfo(): Promise<JsonRpcResponse<any>>
abciQuery(params: AbciQuery): Promise<JsonRpcResponse<any>>
block(params?: Height): Promise<JsonRpcResponse<any>>
blockResult(params?: Height): Promise<JsonRpcResponse<any>>
blockchain(params?: Blockchain): Promise<JsonRpcResponse<any>>
commit(params?: Height): Promise<JsonRpcResponse<any>>
tx(params: Tx): Promise<JsonRpcResponse<any>>
broadcastTxAsync(params: Broadcast): Promise<JsonRpcResponse<any>>
broadcastTxCommit(params: Broadcast): Promise<JsonRpcResponse<any>>
broadcastTxSync(params: Broadcast): Promise<JsonRpcResponse<any>>
txSearch(params: TxSearch): Promise<JsonRpcResponse<any>>
validators(params?: Validators): Promise<JsonRpcResponse<any>>
unconfirmedTxs(params: UnconfirmedTxs): Promise<JsonRpcResponse<any>>
genesis(): Promise<JsonRpcResponse<any>>
health(): Promise<JsonRpcResponse<any>>
netInfo(): Promise<JsonRpcResponse<any>>
numUnconfirmedTxs(): Promise<JsonRpcResponse<any>>
}

export interface JsonBnbRpcCall {
id: number | string
jsonrpc: string
method: string
params?: Params
}

export interface Params {
[key: string]: unknown;
}

export interface AbstractBnbRpcInterface {
rawRpcCall(body: JsonBnbRpcCall): Promise<JsonRpcResponse<any>>
destroy(): void
getRpcNodeUrl(): string
}

export interface BnbRpcSuite extends BnbRpcInterface, AbstractBnbRpcInterface {}
73 changes: 73 additions & 0 deletions src/e2e/rpc/other/tatum.rpc.bnb.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as process from 'process'
import { Bnb, Network, TatumSDK } from '../../../service'
import { e2eUtil } from '../../e2e.util'

const getBnbRpc = async () =>
await TatumSDK.init<Bnb>({
network: Network.BNB,
apiKey: {
v4: process.env.V4_API_KEY_MAINNET
},
verbose: e2eUtil.isVerbose,
})

// Testnet is not available
describe('Bnb', () => {
describe('mainnet', () => {
it('block', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.block()
await tatum.destroy()
expect(result).toBeDefined()
})

it('abciInfo', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.abciInfo()
await tatum.destroy()
expect(result).toBeDefined()
})

it('blockchain', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.blockchain()
await tatum.destroy()
expect(result).toBeDefined()
})

it('health', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.health()
await tatum.destroy()
expect(result).toBeDefined()
})

it('genesis', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.genesis()
await tatum.destroy()
expect(result).toBeDefined()
})

it('validators', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.validators()
await tatum.destroy()
expect(result).toBeDefined()
})

it('unconfirmedTxs', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.unconfirmedTxs({ limit: '1' })
await tatum.destroy()
expect(result).toBeDefined()
})

it('raw rpc call', async () => {
const tatum = await getBnbRpc()
const { result } = await tatum.rpc.rawRpcCall({ method: 'block', id: 1, jsonrpc: '2.0', params: {} })
await tatum.destroy()
expect(result).toBeDefined()
})
})
})
91 changes: 91 additions & 0 deletions src/service/rpc/other/AbstractBnbRpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { JsonRpcResponse } from '../../../dto'
import { Height, AbciQuery, BnbRpcInterface, Blockchain, Tx, Broadcast, TxSearch } from '../../../dto/rpc/BnbRpcSuite'
import { PostI } from '../../../dto/PostI'
import { Utils } from '../../../util'

export abstract class AbstractBnbRpc implements BnbRpcInterface {
protected abstract post<T>(post: PostI): Promise<T>

sendRpcCall<T, U>(method: string, params?: T): Promise<U> {
const body = {
id: 1,
jsonrpc: '2.0',
method,
params: params ? Utils.convertObjCamelToSnake(params) : {},
}
return this.post({ body, path: '' })
}

status(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('status')
}

abciInfo(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('abci_info')
}

abciQuery(params: AbciQuery): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('abci_query', params)
}

block(params?: Height): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('block', params)
}

blockResult(params?: Height): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('block_result', params)
}

blockchain(params?: Blockchain): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('blockchain', params)
}

commit(params?: Height): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('commit', params)
}

tx(params: Tx): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('tx', params)
}

broadcastTxAsync(params: Broadcast): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('broadcast_tx_async', params)
}

broadcastTxCommit(params: Broadcast): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('broadcast_tx_commit', params)
}

broadcastTxSync(params: Broadcast): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('broadcast_tx_sync', params)
}

txSearch(params: TxSearch): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('tx_search', params)
}

validators(params: Height): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('validators', params)
}

unconfirmedTxs(params: { limit: string }): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('unconfirmed_txs', params)
}

genesis(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('genesis')
}

health(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('health')
}

netInfo(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('net_info')
}

numUnconfirmedTxs(): Promise<JsonRpcResponse<any>> {
return this.sendRpcCall('num_unconfirmed_txs')
}
}
38 changes: 38 additions & 0 deletions src/service/rpc/other/BnbLoadBalancerRpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Container, Service } from 'typedi'
import { LoadBalancer } from '../generic'
import { AbstractBnbRpc } from './AbstractBnbRpc'
import { BnbRpcSuite, JsonBnbRpcCall } from '../../../dto/rpc/BnbRpcSuite'
import { JsonRpcResponse } from '../../../dto'
import { PostI } from '../../../dto/PostI'

@Service({
factory: (data: { id: string }) => {
return new BnbLoadBalancerRpc(data.id)
},
transient: true,
})
export class BnbLoadBalancerRpc extends AbstractBnbRpc implements BnbRpcSuite {
protected readonly loadBalancer: LoadBalancer

constructor(id: string) {
super()
this.loadBalancer = Container.of(id).get(LoadBalancer)
}

public destroy() {
this.loadBalancer.destroy()
}

getRpcNodeUrl(): string {
return this.loadBalancer.getActiveNormalUrlWithFallback().url
}

rawRpcCall(body: JsonBnbRpcCall): Promise<JsonRpcResponse<any>> {
return this.loadBalancer.post({ body, path: '' })
}

protected post<T>(post: PostI): Promise<T> {
return this.loadBalancer.post(post)
}
}
14 changes: 14 additions & 0 deletions src/service/tatum/tatum.other.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Notification } from '../notification'
import { Rates } from '../rate'
import { Token } from '../token'
import { TatumSdkChain } from './tatum'
import { BnbRpcSuite } from '../../dto/rpc/BnbRpcSuite'

export abstract class BaseOther extends TatumSdkChain {
ipfs: Ipfs
Expand All @@ -22,6 +23,19 @@ export abstract class BaseOther extends TatumSdkChain {
}
}

export class Bnb extends BaseOther {
rpc: BnbRpcSuite
notification: Notification
address: Address

constructor(id: string) {
super(id)
this.rpc = Utils.getRpc<BnbRpcSuite>(id, Container.of(id).get(CONFIG))
this.notification = Container.of(id).get(Notification)
this.address = Container.of(id).get(Address)
}
}

export class Xrp extends BaseOther {
rpc: XrpRpcInterface
notification: Notification
Expand Down
2 changes: 2 additions & 0 deletions src/util/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export const Constant = {
[Network.HAQQ]: 18,
[Network.HAQQ_TESTNET]: 18,
[Network.CHILIZ]: 18,
[Network.BNB]: 18,
},
CURRENCY_NAMES: {
[Network.BITCOIN]: 'BTC',
Expand Down Expand Up @@ -256,6 +257,7 @@ export const Constant = {
[Network.HAQQ]: 'HAQQ',
[Network.HAQQ_TESTNET]: 'HAQQ',
[Network.CHILIZ]: 'CHILIZ',
[Network.BNB]: 'BNB',
},
RPC: {
MAINNETS: [
Expand Down
Loading

0 comments on commit 4f7231b

Please sign in to comment.