Skip to main content

Using ckETH in dapps

Advanced
Ethereum

ckETH is an ICRC-2 compliant token, meaning it supports the ICRC-1 and ICRC-2 token standards.

To integrate ckETH into your dapp, you can simply write code that uses the ICRC-1 and ICRC-2 standards. For token transfers and account balances, ckETH requests must be sent to the ckETH ledger canister with principal ID ss2fx-dyaaa-aaaar-qacoq-cai.

Write a smart contract that uses ckETH

To write canister code that makes calls to the ckETH ledger, you will need to use inter-canister calls and specify the principal ID of the ckETH ledger canister. Then, to interact with ckETH, you can use the ICRC-1 endpoints.

You can deploy the ckETH ledger locally for testing. Learn more in the ckETH ledger documentation.

Once you have your project configured to use the ckETH ledger, you can interact with it for workflows such as transferring tokens:

import ckethLedger "canister:ledger";
import Debug "mo:base/Debug";
import Result "mo:base/Result";
import Option "mo:base/Option";
import Blob "mo:base/Blob";
import Error "mo:base/Error";

actor {

type Account = {
owner : Principal;
subaccount : ?[Nat8];
};

type TransferArgs = {
amount : Nat;
toAccount : Account;
};

public shared ({ caller }) func transfer(args : TransferArgs) : async Result.Result<ckethLedger.BlockIndex, Text> {
Debug.print(
"Transferring "
# debug_show (args.amount)
# " tokens to account"
# debug_show (args.toAccount)
);

let transferArgs : ckethLedger.TransferArg = {
// can be used to distinguish between transactions
memo = null;
// the amount we want to transfer
amount = args.amount;
// we want to transfer tokens from the default subaccount of the canister
from_subaccount = null;
// if not specified, the default fee for the canister is used
fee = null;
// we take the principal and subaccount from the arguments and convert them into an account identifier
to = args.toAccount;
// a timestamp indicating when the transaction was created by the caller; if it is not specified by the caller then this is set to the current ICP time
created_at_time = null;
};

try {
// initiate the transfer
let transferResult = await ckethLedger.icrc1_transfer(transferArgs);

// check if the transfer was successful
switch (transferResult) {
case (#Err(transferError)) {
return #err("Couldn't transfer funds:\n" # debug_show (transferError));
};
case (#Ok(blockIndex)) { return #ok blockIndex };
};
} catch (error : Error) {
// catch any errors that might occur during the transfer
return #err("Reject message: " # Error.message(error));
};
};
};

View the ICRC-1 and ICRC-2 endpoints for more information on sending and receiving tokens.