Skip to content

Commit

Permalink
ALL-6929 Add zkSync rpc (#1122)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hathoriel authored Jul 23, 2024
1 parent 9c5cced commit 7df5678
Show file tree
Hide file tree
Showing 17 changed files with 435 additions and 107 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [4.2.37] - 2024.7.23

### Added

- Support for zkSync mainnet & testnet

## [4.2.36] - 2024.7.18

### Added
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.2.36",
"version": "4.2.37",
"description": "Tatum JS SDK",
"author": "Tatum",
"repository": "https://github.com/tatumio/tatum-js",
Expand Down
3 changes: 2 additions & 1 deletion src/dto/Currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export enum Currency {
ATOM = 'ATOM',
IOTA = 'IOTA',
CSPR = 'CSPR',
TON = 'TON'
TON = 'TON',
ZKS = 'ZKS',
}

export function networkToCurrency(network: Network): Currency {
Expand Down
24 changes: 22 additions & 2 deletions src/dto/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export enum Network {
BITCOIN_ELECTRS = 'bitcoin-mainnet-electrs',
CASPER = 'casper-mainnet',
TON = 'ton-mainnet',
ZK_SYNC = 'zks-mainnet',


// Testnets
Expand Down Expand Up @@ -111,7 +112,8 @@ export enum Network {
IOTA_TESTNET = 'iota-testnet',
BITCOIN_ELECTRS_TESTNET = 'bitcoin-testnet-electrs',
ROSTRUM_TESTNET = 'bch-testnet-rostrum',
TON_TESTNET = 'ton-testnet'
TON_TESTNET = 'ton-testnet',
ZK_SYNC_TESTNET = 'zks-testnet',
}

export const EVM_BASED_NETWORKS = [
Expand Down Expand Up @@ -163,6 +165,8 @@ export const EVM_BASED_NETWORKS = [
Network.HORIZEN_EON,
Network.HORIZEN_EON_GOBI,
Network.CHILIZ,
Network.ZK_SYNC,
Network.ZK_SYNC_TESTNET,
]

export const UTXO_BASED_NETWORKS = [
Expand Down Expand Up @@ -216,6 +220,8 @@ export const UTXO_LOAD_BALANCER_NETWORKS = [

export const DOGECOIN_LOAD_BALANCED_NETWORKS = [Network.DOGECOIN, Network.DOGECOIN_TESTNET]

export const ZK_SYNC_LOAD_BALANCER_NETWORKS = [Network.ZK_SYNC, Network.ZK_SYNC_TESTNET]

export const EVM_LOAD_BALANCER_NETWORKS = [
Network.FLARE,
Network.FLARE_COSTON,
Expand Down Expand Up @@ -243,8 +249,10 @@ export const EVM_LOAD_BALANCER_NETWORKS = [
Network.FANTOM,
Network.CRONOS,
Network.BASE,
...ZK_SYNC_LOAD_BALANCER_NETWORKS,
]


export const TRON_LOAD_BALANCER_NETWORKS = [Network.TRON]
export const EOS_LOAD_BALANCER_NETWORKS = [Network.EOS]
export const XRP_LOAD_BALANCER_NETWORKS = [Network.XRP, Network.XRP_TESTNET]
Expand Down Expand Up @@ -390,6 +398,8 @@ export const isIotaNetwork = (network: Network) => IOTA_NETWORKS.includes(networ

export const isElectrsNetwork = (network: Network) => BITCOIN_ELECTRS_NETWORKS.includes(network)

export const isZkSyncNetwork = (network: Network) => ZK_SYNC_LOAD_BALANCER_NETWORKS.includes(network)

export const isCasperNetwork = (network: Network) => CASPER_NETWORKS.includes(network)

export const isTonNetwork = (network: Network) => TON_NETWORKS.includes(network)
Expand Down Expand Up @@ -974,5 +984,15 @@ export const NETWORK_METADATA: Record<Network, NetworkMetadata> = {
[Network.TON_TESTNET]: {
currency: Currency.TON,
testnet: true
}
},
[Network.ZK_SYNC]: {
currency: Currency.ZKS,
testnet: false,
chainId: 324
},
[Network.ZK_SYNC_TESTNET]: {
currency: Currency.ZKS,
testnet: true,
chainId: 300
},
}
84 changes: 84 additions & 0 deletions src/dto/rpc/ZkSyncRpcSuite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { EvmBasedRpcInterface, TxPayload } from './EvmBasedRpcInterface'
import { JsonRpcResponse } from '../JsonRpcResponse.dto'
import { BigNumber } from 'bignumber.js'
import { AbstractRpcInterface } from './AbstractJsonRpcInterface'

export interface BridgeContracts {
l1Erc20DefaultBridge: string
l2Erc20DefaultBridge: string
l1WethBridge: string
l2WethBridge: string
}

export interface TokenDetails {
l1Address: string
l2Address: string
name: string
symbol: string
decimals: number
}

export interface TokenMapping {
[key: string]: string
}

export interface ZksGetL2ToL1MsgProofParams {
block: number
sender: string
msg: string
l2_log_position?: string
}

export interface ZksGetL2ToL1ProofResponse {
id: string
proof: string[]
root: string
}

export interface GetProofParams {
data: string
arrayOfData: string[]
timePoint: number
}

export interface StorageProof {
key: string;
value: string;
index: number;
proof: string[];
}

export interface GetProofResponse {
address: string;
storageProof: StorageProof[];
}

export interface ZkSyncRpcSuite extends ZkSyncRpcInterface, AbstractRpcInterface {}

export interface ZkSyncRpcInterface extends EvmBasedRpcInterface {
zksEstimateFee(payload: TxPayload): Promise<JsonRpcResponse<any>>
zksEstimateGasL1ToL2(payload: TxPayload): Promise<JsonRpcResponse<BigNumber>>
zksGetBridgeHubContract(): Promise<JsonRpcResponse<string>>
zksGetMinContract(): Promise<JsonRpcResponse<string>>
zksGetBridgeContracts(): Promise<JsonRpcResponse<BridgeContracts>>
zksL1ChainId(): Promise<JsonRpcResponse<BigNumber>>
zksGetBaseTokenL1Address(): Promise<JsonRpcResponse<string>>
zksGetConfirmedTokens(tokenIdToStart: number, maxTokens: number): Promise<JsonRpcResponse<TokenDetails[]>>
zksGetAllAccountBalances(address: string): Promise<JsonRpcResponse<TokenMapping>>
zksGetL2ToL1MsgProof(payload: ZksGetL2ToL1MsgProofParams): Promise<JsonRpcResponse<ZksGetL2ToL1ProofResponse>>
zksGetL2ToL1LogProof(txHash: string, logIndex?: number): Promise<JsonRpcResponse<ZksGetL2ToL1ProofResponse>>
zksL1BatchNumber(): Promise<JsonRpcResponse<BigNumber>>
zksGetBlockDetails(blockNumber: number): Promise<JsonRpcResponse<any>>
zksGetTransactionDetails(txHash: string): Promise<JsonRpcResponse<any>>
zksGetRawBlockTransactions(blockNumber: number): Promise<JsonRpcResponse<any>>
zksGetL1BatchDetails(batchNumber: number): Promise<JsonRpcResponse<any>>
zksGetBytecodeByHash(txHash: string): Promise<JsonRpcResponse<number[]>>
zksGetL1BatchBlockRange(batchNumber: number): Promise<JsonRpcResponse<string[]>>
zksGetL1GasPrice(): Promise<JsonRpcResponse<BigNumber>>
zksGetFeeParams(): Promise<JsonRpcResponse<any>>
zksGetProtocolVersion(versionId?: number): Promise<JsonRpcResponse<any>>
zksGetProof(payload: GetProofParams): Promise<JsonRpcResponse<GetProofResponse>>
zksSendRawTransactionWithDetailedOutput(data: string): Promise<JsonRpcResponse<any>>
}
13 changes: 11 additions & 2 deletions src/e2e/e2e.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import {
FullSdk,
Network,
NotificationSubscription,
RpcNodeType,
TatumConfig,
} from '../service'
import { ResponseDto } from '../util'
import { NetworkUtils } from '../util/network.utils'

export const e2eUtil = {
initConfig: (network: Network, apiKey?: string) => {
return {
initConfig: (network: Network, apiKey?: string, url?: string) => {
const config: TatumConfig = {
network,
verbose: e2eUtil.isVerbose,
retryCount: 5,
Expand All @@ -23,6 +25,13 @@ export const e2eUtil = {
v4: apiKey ?? NetworkUtils.getV4ApiKeyForNetwork(network),
},
}

if (url) {
config.rpc = {
nodes: [{ url: url, type: RpcNodeType.NORMAL }]
}
}
return config
},
subscriptions: {
getAddress: (network: Network): string => {
Expand Down
19 changes: 10 additions & 9 deletions src/e2e/rpc/evm/evm.e2e.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ interface EvmE2eI {
estimateGas?: any
}
skipEstimateGas?: boolean
url?: string
}

export const EvmE2eUtils = {
initTatum: async <T extends BaseEvm>(network: Network, apiKey?: string) =>
TatumSDK.init<T>(e2eUtil.initConfig(network, apiKey)),
initTatum: async <T extends BaseEvm>(network: Network, apiKey?: string, url?: string) =>
TatumSDK.init<T>(e2eUtil.initConfig(network, apiKey, url)),
e2e: (evmE2eI: EvmE2eI) => {
const { network, data, skipEstimateGas, apiKey } = evmE2eI
const { network, data, skipEstimateGas, apiKey, url } = evmE2eI
it('eth_blockNumber', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const { result } = await tatum.rpc.blockNumber()

await tatum.destroy()
expect(result?.toNumber()).toBeGreaterThan(0)
})

it('eth_chainId', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const { result } = await tatum.rpc.chainId()

tatum.rpc.destroy()
Expand All @@ -36,7 +37,7 @@ export const EvmE2eUtils = {

if (!skipEstimateGas) {
it('eth_estimateGas', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const estimateGas = data?.estimateGas ?? {
from: '0xb4c9E4617a16Be36B92689b9e07e9F64757c1792',
to: '0x4675C7e5BaAFBFFbca748158bEcBA61ef3b0a263',
Expand All @@ -49,23 +50,23 @@ export const EvmE2eUtils = {
}

it('eth_gasPrice', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const { result } = await tatum.rpc.gasPrice()

await tatum.destroy()
expect(result?.toNumber()).toBeGreaterThan(0)
})

it('web3_clientVersion', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const { result } = await tatum.rpc.clientVersion()

await tatum.destroy()
expect(result).toBeTruthy()
})

it('eth_getBlockByNumber', async () => {
const tatum = await EvmE2eUtils.initTatum(network, apiKey)
const tatum = await EvmE2eUtils.initTatum(network, apiKey, url)
const { result } = await tatum.rpc.blockNumber()
const { result: block } = await tatum.rpc.getBlockByNumber((result as BigNumber).toNumber() - 1000)
await tatum.destroy()
Expand Down
8 changes: 5 additions & 3 deletions src/e2e/rpc/evm/evm.rpc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const testNetworks = [
},
{ network: Network.FLARE },
{ network: Network.FLARE_SONGBIRD },
{ network: Network.FLARE_COSTON },
// { network: Network.FLARE_COSTON },
{ network: Network.FLARE_COSTON_2 },
{ network: Network.ETHEREUM },
{ network: Network.ETHEREUM_SEPOLIA },
{ network: Network.ETHEREUM_HOLESKY },
{ network: Network.FANTOM },
{ network: Network.FANTOM_TESTNET, apiKey: process.env.V3_API_KEY_TESTNET },
// { network: Network.FANTOM },
// { network: Network.FANTOM_TESTNET, apiKey: process.env.V3_API_KEY_TESTNET },
{ network: Network.ETHEREUM_CLASSIC },
// { network: Network.POLYGON },
{ network: Network.POLYGON_AMOY },
Expand Down Expand Up @@ -71,6 +71,8 @@ const testNetworks = [
// { network: Network.CRONOS },
{ network: Network.CRONOS_TESTNET, apiKey: process.env.V3_API_KEY_TESTNET },
{ network: Network.BASE },
{ network: Network.ZK_SYNC, url: 'https://mainnet.era.zksync.io' },
{ network: Network.ZK_SYNC_TESTNET, url: 'https://sepolia.era.zksync.dev' },
]

describe.each(testNetworks)('RPC EVM', (testNetwork) => {
Expand Down
47 changes: 47 additions & 0 deletions src/e2e/rpc/evm/tatum.rpc.zksync.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Network, ZkSync } from '../../../service'
import { EvmE2eUtils } from './evm.e2e.utils'

const run = async (network: Network, url: string) => {
it('zks_getL1GasPrice', async () => {
const tatum = await EvmE2eUtils.initTatum<ZkSync>(network, undefined, url)
const { result } = await tatum.rpc.zksGetL1GasPrice()

await tatum.destroy()
expect(result).toBeDefined()
})

it('zks_getBlockDetails', async () => {
const tatum = await EvmE2eUtils.initTatum<ZkSync>(network, undefined, url)
const { result } = await tatum.rpc.zksGetBlockDetails(39830202)

await tatum.destroy()
expect(result).toBeDefined()
})

it('zks_getBaseTokenL1Address', async () => {
const tatum = await EvmE2eUtils.initTatum<ZkSync>(network, undefined, url)
const { result } = await tatum.rpc.zksGetBaseTokenL1Address()

await tatum.destroy()
expect(result).toBeDefined()
})

it('zks_getFeeParams', async () => {
const tatum = await EvmE2eUtils.initTatum<ZkSync>(network, undefined, url)
const { result } = await tatum.rpc.zksGetFeeParams()

await tatum.destroy()
expect(result).toBeDefined()

})
}

describe.each([
{ network: Network.ZK_SYNC, url: 'https://mainnet.era.zksync.io' },
{ network: Network.ZK_SYNC_TESTNET, url: 'https://sepolia.era.zksync.dev'},
])('RPC ZkSync', (network) => {
const { network: networkName, url } = network
describe(networkName, () => {
run(networkName, url)
})
})
Loading

0 comments on commit 7df5678

Please sign in to comment.