Skip to content

Commit

Permalink
candid: L2 chains (Arbitrum, Base, Optimism) (#212)
Browse files Browse the repository at this point in the history
* Progress

* Progress

* Add tests

* Misc

* Update Cargo hash

* Fill match arms for 'resolve_rpc_service()'

* Misc

* Reformat

* Add built-in RPC services

* Fix

* Update E2E tests

* Account for inconsistent 'TooFewCycles' errors in E2E tests

* Rename 'ArbitrumMainnet' -> 'ArbitrumOne'

* More renaming

* Reformat
  • Loading branch information
rvanasa authored May 23, 2024
1 parent aa5cc2a commit 2dd68fa
Show file tree
Hide file tree
Showing 9 changed files with 474 additions and 204 deletions.
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ ic-stable-structures = { workspace = true }
ic-certified-map = { workspace = true }
ic-cdk = { workspace = true }
ic-cdk-macros = { workspace = true }
ic-canister-log = { git = "https://github.com/dfinity/ic", rev = "2e79e7af9a6fa15633d73af69fb021a0ae74df6c", package = "ic-canister-log" }
cketh-common = { git = "https://github.com/dfinity/ic", rev = "2e79e7af9a6fa15633d73af69fb021a0ae74df6c", package = "ic-cketh-minter" }
ic-canister-log = { git = "https://github.com/dfinity/ic", rev = "0f6a050f402248ee611631ce4855b86ae3414ced", package = "ic-canister-log" }
cketh-common = { git = "https://github.com/dfinity/ic", rev = "0f6a050f402248ee611631ce4855b86ae3414ced", package = "ic-cketh-minter" }
maplit = "1.0"
num = "0.4"
num-traits = "0.2"
Expand Down
49 changes: 33 additions & 16 deletions candid/evm_rpc.did
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ type EthMainnetService = variant {
Cloudflare;
PublicNode;
};
type EthSepoliaService = variant { Alchemy; Ankr; BlockPi; PublicNode };
type EthSepoliaService = variant {
Alchemy;
Ankr;
BlockPi;
PublicNode;
};
type L2MainnetService = variant {
Alchemy;
Ankr;
BlockPi;
PublicNode;
};
type FeeHistory = record {
reward : vec vec nat;
gasUsedRatio : vec float64;
Expand Down Expand Up @@ -175,19 +186,25 @@ type RpcError = variant {
};
type RpcApi = record { url : text; headers : opt vec HttpHeader };
type RpcService = variant {
EthSepolia : EthSepoliaService;
EthMainnet : EthMainnetService;
Chain : nat64;
Provider : nat64;
Custom : RpcApi;
EthSepolia : EthSepoliaService;
EthMainnet : EthMainnetService;
ArbitrumOne : L2MainnetService;
BaseMainnet : L2MainnetService;
OptimismMainnet : L2MainnetService;
};
type RpcServices = variant {
EthSepolia : opt vec EthSepoliaService;
EthMainnet : opt vec EthMainnetService;
Custom : record {
chainId : nat64;
services : vec RpcApi;
};
EthSepolia : opt vec EthSepoliaService;
EthMainnet : opt vec EthMainnetService;
ArbitrumOne : opt vec L2MainnetService;
BaseMainnet : opt vec L2MainnetService;
OptimismMainnet : opt vec L2MainnetService;
};
type SendRawTransactionStatus = variant {
Ok : opt text;
Expand Down Expand Up @@ -231,29 +248,29 @@ type ValidationError = variant {
CredentialHeaderNotAllowed;
};
service : (InitArgs) -> {
authorize : (principal, Auth) -> (success: bool);
deauthorize : (principal, Auth) -> (success: bool);
authorize : (principal, Auth) -> (success : bool);
deauthorize : (principal, Auth) -> (success : bool);
eth_feeHistory : (RpcServices, opt RpcConfig, FeeHistoryArgs) -> (MultiFeeHistoryResult);
eth_getBlockByNumber : (RpcServices, opt RpcConfig, BlockTag) -> (MultiGetBlockByNumberResult);
eth_getLogs : (RpcServices, opt RpcConfig, GetLogsArgs) -> (MultiGetLogsResult);
eth_getTransactionCount : (RpcServices, opt RpcConfig, GetTransactionCountArgs) -> (
MultiGetTransactionCountResult
);
eth_getTransactionReceipt : (RpcServices, opt RpcConfig, hash: text) -> (MultiGetTransactionReceiptResult);
eth_sendRawTransaction : (RpcServices, opt RpcConfig, rawSignedTransactionHex: text) -> (MultiSendRawTransactionResult);
getAccumulatedCycleCount : (ProviderId) -> (cycles: nat) query;
eth_getTransactionReceipt : (RpcServices, opt RpcConfig, hash : text) -> (MultiGetTransactionReceiptResult);
eth_sendRawTransaction : (RpcServices, opt RpcConfig, rawSignedTransactionHex : text) -> (MultiSendRawTransactionResult);
getAccumulatedCycleCount : (ProviderId) -> (cycles : nat) query;
getAuthorized : (Auth) -> (vec principal) query;
getMetrics : () -> (Metrics) query;
getNodesInSubnet : () -> (numberOfNodes: nat32) query;
getOpenRpcAccess : () -> (active: bool) query;
getNodesInSubnet : () -> (numberOfNodes : nat32) query;
getOpenRpcAccess : () -> (active : bool) query;
getProviders : () -> (vec ProviderView) query;
getServiceProviderMap : () -> (vec record { RpcService; nat64 }) query;
manageProvider : (ManageProviderArgs) -> ();
registerProvider : (RegisterProviderArgs) -> (nat64);
request : (RpcService, json: text, maxResponseBytes: nat64) -> (RequestResult);
requestCost : (RpcService, json: text, maxResponseBytes: nat64) -> (RequestCostResult) query;
setOpenRpcAccess : (active: bool) -> ();
request : (RpcService, json : text, maxResponseBytes : nat64) -> (RequestResult);
requestCost : (RpcService, json : text, maxResponseBytes : nat64) -> (RequestCostResult) query;
setOpenRpcAccess : (active : bool) -> ();
unregisterProvider : (ProviderId) -> (bool);
updateProvider : (UpdateProviderArgs) -> ();
withdrawAccumulatedCycles : (ProviderId, recipient: principal) -> ();
withdrawAccumulatedCycles : (ProviderId, recipient : principal) -> ();
};
50 changes: 30 additions & 20 deletions e2e/motoko/main.mo
Original file line number Diff line number Diff line change
Expand Up @@ -149,39 +149,49 @@ shared ({ caller = installer }) actor class Main() {
};
};

let candidRpcCycles = 100_000_000_000;
// Any unused cycles will be refunded
let candidRpcCycles = 200_000_000_000;
let allServices : [(Text, EvmRpc.RpcServices)] = [
(
"Ethereum",
#EthMainnet(?[#Alchemy, #Ankr, #Cloudflare, #BlockPi, #PublicNode]),
),
(
"Arbitrum",
#Custom {
chainId = 42161;
services = [{
url = "https://rpc.ankr.com/arbitrum";
headers = null;
}];
},
#ArbitrumOne(null),
),
(
"Base",
#Custom {
chainId = 8453;
services = [{
url = "https://mainnet.base.org";
headers = null;
}];
},
#BaseMainnet(null),
),
(
"Optimism",
#OptimismMainnet(null),
),
];

func testCandidRpc(networkName : Text, services : EvmRpc.RpcServices) : async () {
switch (await canister.eth_getBlockByNumber(services, null, #Latest)) {
case (#Consistent(#Err(#ProviderError(#TooFewCycles _)))) {};
case result {
addError("Received unexpected result for " # networkName # ": " # debug_show result);
let expected = switch result {
case (#Inconsistent(results)) {
var expected = true;
for (result in results.vals()) {
switch result {
case (_service, #Err(#ProviderError(#TooFewCycles _))) {};
case _ {
expected := false;
};
};
};
expected;
};
case _ { false };
};
if (not expected) {
addError("Received unexpected `eth_getBlockByNumber` result for " # networkName # ": " # debug_show result);
};
};
};

Expand Down Expand Up @@ -246,10 +256,7 @@ shared ({ caller = installer }) actor class Main() {
),
);
switch services {
case (#Custom _) {
// Skip sending transaction for custom chains due to chain ID mismatch
};
case _ {
case (#EthMainnet(_)) {
Cycles.add<system>(candidRpcCycles);
assertOk(
networkName,
Expand All @@ -261,6 +268,9 @@ shared ({ caller = installer }) actor class Main() {
),
);
};
case _ {
// Skip sending transaction for non-Ethereum chains due to chain ID mismatch
};
};
};

Expand Down
Loading

0 comments on commit 2dd68fa

Please sign in to comment.