-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add canister init args #112
Changes from all commits
6b12527
b2b19a3
f4b97ba
cd01b90
cb68046
08d54c5
7692193
7c4fb1c
366a9bc
13ff27b
418273f
b4b4c28
9f835d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,149 +1,177 @@ | ||
import EvmRpcCanister "canister:evm_rpc"; | ||
import EvmRpcFidicuaryCanister "canister:evm_rpc_fiduciary"; | ||
|
||
import Principal "mo:base/Principal"; | ||
import Evm "mo:evm"; | ||
import Blob "mo:base/Blob"; | ||
import Debug "mo:base/Debug"; | ||
import Cycles "mo:base/ExperimentalCycles"; | ||
import Principal "mo:base/Principal"; | ||
import Text "mo:base/Text"; | ||
import Blob "mo:base/Blob"; | ||
import Cycles "mo:base/ExperimentalCycles" | ||
import Evm "mo:evm"; | ||
|
||
shared ({ caller = installer }) actor class Main() { | ||
let mainnet = Evm.Rpc( | ||
#Canister EvmRpcCanister, | ||
#Service { | ||
hostname = "cloudflare-eth.com"; | ||
network = ? #EthMainnet; | ||
}, | ||
); | ||
|
||
public shared ({ caller }) func test() : async () { | ||
assert caller == installer; | ||
|
||
let source = #Service { | ||
hostname = "cloudflare-eth.com"; | ||
chainId = ?(1 : Nat64); // Ethereum mainnet | ||
}; | ||
let json = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_gasPrice\",\"params\":null,\"id\":1}"; | ||
let maxResponseBytes : Nat64 = 1000; | ||
let canisterDetails = [ | ||
// (`canister module`, `debug name`, `nodes in subnet`, `expected cycles for JSON-RPC call`) | ||
(EvmRpcCanister, "default", 13, 521_498_000), | ||
(EvmRpcFidicuaryCanister, "fiduciary", 28, 1_123_226_461), | ||
Comment on lines
+17
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not clear what these numbers mean (readers may be able to guess what 13 and 28 mean but not the other numbers). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a comment to clarify. There's also a line directly after this which shows the variable names for each tuple entry, although I see how it could be easy to miss. |
||
]; | ||
for ((canister, name, nodesInSubnet, expectedCycles) in canisterDetails.vals()) { | ||
Debug.print("Testing " # name # " canister..."); | ||
|
||
// `requestCost()` | ||
let cyclesResult = await EvmRpcCanister.requestCost(source, json, maxResponseBytes); | ||
let cycles = switch cyclesResult { | ||
case (#Ok cycles) { cycles }; | ||
case (#Err err) { | ||
Debug.trap("unexpected error for `request_cost`: " # (debug_show err)); | ||
let mainnet = Evm.Rpc( | ||
#Canister canister, | ||
#Service { | ||
hostname = "cloudflare-eth.com"; | ||
network = ? #EthMainnet; | ||
}, | ||
); | ||
|
||
let source = #Service { | ||
hostname = "cloudflare-eth.com"; | ||
chainId = ?(1 : Nat64); // Ethereum mainnet | ||
}; | ||
}; | ||
let json = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_gasPrice\",\"params\":null,\"id\":1}"; | ||
let maxResponseBytes : Nat64 = 1000; | ||
|
||
// `request()` without cycles | ||
let resultWithoutCycles = await EvmRpcCanister.request(source, json, maxResponseBytes); | ||
assert switch resultWithoutCycles { | ||
case (#Err(#ProviderError(#TooFewCycles { expected }))) expected == cycles; | ||
case _ false; | ||
}; | ||
// `requestCost()` | ||
let cyclesResult = await canister.requestCost(source, json, maxResponseBytes); | ||
let cycles = switch cyclesResult { | ||
case (#Ok cycles) { cycles }; | ||
case (#Err err) { | ||
Debug.trap("unexpected error for `request_cost`: " # (debug_show err)); | ||
}; | ||
}; | ||
if (cycles != expectedCycles) { | ||
Debug.trap("unexpected number of cycles for " # name # " canister: " # debug_show cycles # " (expected " # debug_show expectedCycles # ")"); | ||
}; | ||
|
||
// `request()` without cycles | ||
let resultWithoutCycles = await canister.request(source, json, maxResponseBytes); | ||
assert switch resultWithoutCycles { | ||
case (#Err(#ProviderError(#TooFewCycles { expected }))) expected == cycles; | ||
case _ false; | ||
}; | ||
|
||
// `request()` with cycles | ||
let result = await mainnet.request("eth_gasPrice", #Array([]), 1000); | ||
label validate { | ||
switch result { | ||
case (#ok(#Object fields)) { | ||
for ((key, val) in fields.vals()) { | ||
switch (key, val) { | ||
case ("result", #String val) { | ||
assert Text.startsWith(val, #text "0x"); | ||
break validate; | ||
// `request()` with cycles | ||
let result = await mainnet.request("eth_gasPrice", #Array([]), 1000); | ||
label validate { | ||
switch result { | ||
case (#ok(#Object fields)) { | ||
for ((key, val) in fields.vals()) { | ||
switch (key, val) { | ||
case ("result", #String val) { | ||
assert Text.startsWith(val, #text "0x"); | ||
break validate; | ||
}; | ||
case _ {}; | ||
}; | ||
case _ {}; | ||
}; | ||
}; | ||
case _ {}; | ||
}; | ||
case _ {}; | ||
Debug.trap(debug_show result); | ||
}; | ||
Debug.trap(debug_show result); | ||
}; | ||
|
||
// Candid-RPC methods | ||
type RpcResult<T> = { #Ok : T; #Err : EvmRpcCanister.RpcError }; | ||
type MultiRpcResult<T> = { | ||
#Consistent : RpcResult<T>; | ||
#Inconsistent : [(EvmRpcCanister.RpcService, RpcResult<T>)]; | ||
}; | ||
// `request()` without sufficient cycles | ||
let resultWithoutEnoughCycles = await canister.request(source, json, maxResponseBytes); | ||
Cycles.add(cycles - 1); | ||
assert switch resultWithoutEnoughCycles { | ||
case (#Err(#ProviderError(#TooFewCycles { expected }))) expected == cycles; | ||
case _ false; | ||
}; | ||
|
||
func assertOk<T>(method : Text, result : MultiRpcResult<T>) { | ||
switch result { | ||
case (#Consistent(#Ok _)) {}; | ||
case (#Consistent(#Err err)) { | ||
Debug.trap("received error for " # method # ": " # debug_show err); | ||
}; | ||
case (#Inconsistent(results)) { | ||
for ((service, result) in results.vals()) { | ||
switch result { | ||
case (#Ok(_)) {}; | ||
case (#Err(err)) { | ||
Debug.trap("received error in inconsistent results for " # method # ": " # debug_show err); | ||
// Candid-RPC methods | ||
type RpcResult<T> = { #Ok : T; #Err : canister.RpcError }; | ||
type MultiRpcResult<T> = { | ||
#Consistent : RpcResult<T>; | ||
#Inconsistent : [(canister.RpcService, RpcResult<T>)]; | ||
}; | ||
|
||
func assertOk<T>(method : Text, result : MultiRpcResult<T>) { | ||
switch result { | ||
case (#Consistent(#Ok _)) {}; | ||
case (#Consistent(#Err err)) { | ||
Debug.trap("received error for " # method # ": " # debug_show err); | ||
}; | ||
case (#Inconsistent(results)) { | ||
for ((service, result) in results.vals()) { | ||
switch result { | ||
case (#Ok(_)) {}; | ||
case (#Err(err)) { | ||
Debug.trap("received error in inconsistent results for " # method # ": " # debug_show err); | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
|
||
let candidRpcCycles = 1_000_000_000_000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is there so much code in red and identical-looking code in green below..? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is due to a change in indentation (modified the E2E test to cover both the standard and fiduciary canisters). |
||
let ethMainnetSource = #EthMainnet(?[#Ankr, #BlockPi, #Cloudflare, #PublicNode]); | ||
let candidRpcCycles = 1_000_000_000_000; | ||
let ethMainnetSource = #EthMainnet(?[#Ankr, #BlockPi, #Cloudflare, #PublicNode]); | ||
|
||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getLogs", | ||
await EvmRpcCanister.eth_getLogs( | ||
ethMainnetSource, | ||
{ | ||
addresses = ["0xdAC17F958D2ee523a2206206994597C13D831ec7"]; | ||
fromBlock = null; | ||
toBlock = null; | ||
topics = null; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getBlockByNumber", | ||
await EvmRpcCanister.eth_getBlockByNumber(ethMainnetSource, #Latest), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getTransactionReceipt", | ||
await EvmRpcCanister.eth_getTransactionReceipt(ethMainnetSource, "0xdd5d4b18923d7aae953c7996d791118102e889bea37b48a651157a4890e4746f"), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getTransactionCount", | ||
await EvmRpcCanister.eth_getTransactionCount( | ||
ethMainnetSource, | ||
{ | ||
address = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; | ||
block = #Latest; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_feeHistory", | ||
await EvmRpcCanister.eth_feeHistory( | ||
ethMainnetSource, | ||
{ | ||
blockCount = 3; | ||
newestBlock = #Latest; | ||
rewardPercentiles = null; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_sendRawTransaction", | ||
await EvmRpcCanister.eth_sendRawTransaction( | ||
ethMainnetSource, | ||
"0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83", | ||
), | ||
); | ||
switch (await canister.eth_getBlockByNumber(ethMainnetSource, #Latest)) { | ||
case (#Consistent(#Err(#ProviderError(#TooFewCycles _)))) {}; | ||
case result { | ||
Debug.trap("received unexpected result: " # debug_show result); | ||
}; | ||
}; | ||
|
||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getLogs", | ||
await canister.eth_getLogs( | ||
ethMainnetSource, | ||
{ | ||
addresses = ["0xdAC17F958D2ee523a2206206994597C13D831ec7"]; | ||
fromBlock = null; | ||
toBlock = null; | ||
topics = null; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getBlockByNumber", | ||
await canister.eth_getBlockByNumber(ethMainnetSource, #Latest), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getTransactionReceipt", | ||
await canister.eth_getTransactionReceipt(ethMainnetSource, "0xdd5d4b18923d7aae953c7996d791118102e889bea37b48a651157a4890e4746f"), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_getTransactionCount", | ||
await canister.eth_getTransactionCount( | ||
ethMainnetSource, | ||
{ | ||
address = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; | ||
block = #Latest; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_feeHistory", | ||
await canister.eth_feeHistory( | ||
ethMainnetSource, | ||
{ | ||
blockCount = 3; | ||
newestBlock = #Latest; | ||
rewardPercentiles = null; | ||
}, | ||
), | ||
); | ||
Cycles.add(candidRpcCycles); | ||
assertOk( | ||
"eth_sendRawTransaction", | ||
await canister.eth_sendRawTransaction( | ||
ethMainnetSource, | ||
"0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83", | ||
), | ||
); | ||
}; | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Quick fix for getting below the 2 MB Wasm size limit)