Skip to content

Commit

Permalink
Get USDC balance
Browse files Browse the repository at this point in the history
  • Loading branch information
kristoferlund committed Oct 28, 2024
1 parent 1b6566a commit a3fb927
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/backend/backend.did
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Result_4 = variant { Ok : nat64; Err : text };

service : {
get_address : () -> (Result);
get_balance_usdc : (opt text) -> (Result);
get_balance : (opt text) -> (Result);
get_batch_balances : (vec text) -> (Result);
get_latest_block : () -> (Result);
Expand Down
44 changes: 44 additions & 0 deletions src/backend/src/service/get_balance_usdc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use alloy::{
network::TxSigner,
primitives::{address, Address},
providers::ProviderBuilder,
sol,
transports::icp::IcpConfig,
};

use crate::{create_icp_sepolia_signer, get_rpc_service_sepolia};

// Codegen from ABI file to interact with the contract.
sol!(
#[allow(missing_docs, clippy::too_many_arguments)]
#[sol(rpc)]
USDC,
"abi/USDC.json"
);

/// Request the balance of an ETH account.
#[ic_cdk::update]
async fn get_balance_usdc(address: Option<String>) -> Result<String, String> {
let address = match address {
Some(val) => val,
None => {
let signer = create_icp_sepolia_signer().await;
signer.address().to_string()
}
};
let address = address.parse::<Address>().map_err(|e| e.to_string())?;
let rpc_service = get_rpc_service_sepolia();
let config = IcpConfig::new(rpc_service);
let provider = ProviderBuilder::new().on_icp(config);

let contract = USDC::new(
address!("1c7d4b196cb0c7b01d743fbc6116a902379c7238"),
provider,
);

let result = contract.balanceOf(address).call().await;
match result {
Ok(balance) => Ok(balance._0.to_string()),
Err(e) => Err(e.to_string()),
}
}
1 change: 1 addition & 0 deletions src/backend/src/service/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod get_address;
mod get_balance;
mod get_balance_usdc;
mod get_batch_balances;
mod get_latest_block;
mod send_eth;
Expand Down
3 changes: 1 addition & 2 deletions src/backend/src/service/watch_usdc_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use alloy::{
transports::icp::IcpConfig,
};
use ic_cdk_timers::TimerId;
use USDC::Transfer;

const POLL_LIMIT: usize = 3;

Expand Down Expand Up @@ -105,7 +104,7 @@ async fn watch_usdc_transfer_start() -> Result<String, String> {
.address(usdt_token_address)
// By specifying an `event` or `event_signature` we listen for a specific event of the
// contract. In this case the `Transfer(address,address,uint256)` event.
.event(Transfer::SIGNATURE)
.event(USDC::Transfer::SIGNATURE)
.from_block(BlockNumberOrTag::Latest);

// Initialize the poller and start watching
Expand Down
27 changes: 27 additions & 0 deletions src/frontend/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const SendethwithfillersLazyImport = createFileRoute('/send_eth_with_fillers')()
const SendethLazyImport = createFileRoute('/send_eth')()
const GetlatestblockLazyImport = createFileRoute('/get_latest_block')()
const GetbatchbalancesLazyImport = createFileRoute('/get_batch_balances')()
const GetbalanceusdcLazyImport = createFileRoute('/get_balance_usdc')()
const GetbalanceLazyImport = createFileRoute('/get_balance')()
const GetaddressLazyImport = createFileRoute('/get_address')()
const IndexLazyImport = createFileRoute('/')()
Expand Down Expand Up @@ -72,6 +73,13 @@ const GetbatchbalancesLazyRoute = GetbatchbalancesLazyImport.update({
import('./routes/get_batch_balances.lazy').then((d) => d.Route),
)

const GetbalanceusdcLazyRoute = GetbalanceusdcLazyImport.update({
path: '/get_balance_usdc',
getParentRoute: () => rootRoute,
} as any).lazy(() =>
import('./routes/get_balance_usdc.lazy').then((d) => d.Route),
)

const GetbalanceLazyRoute = GetbalanceLazyImport.update({
path: '/get_balance',
getParentRoute: () => rootRoute,
Expand Down Expand Up @@ -112,6 +120,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof GetbalanceLazyImport
parentRoute: typeof rootRoute
}
'/get_balance_usdc': {
id: '/get_balance_usdc'
path: '/get_balance_usdc'
fullPath: '/get_balance_usdc'
preLoaderRoute: typeof GetbalanceusdcLazyImport
parentRoute: typeof rootRoute
}
'/get_batch_balances': {
id: '/get_batch_balances'
path: '/get_batch_balances'
Expand Down Expand Up @@ -170,6 +185,7 @@ export interface FileRoutesByFullPath {
'/': typeof IndexLazyRoute
'/get_address': typeof GetaddressLazyRoute
'/get_balance': typeof GetbalanceLazyRoute
'/get_balance_usdc': typeof GetbalanceusdcLazyRoute
'/get_batch_balances': typeof GetbatchbalancesLazyRoute
'/get_latest_block': typeof GetlatestblockLazyRoute
'/send_eth': typeof SendethLazyRoute
Expand All @@ -183,6 +199,7 @@ export interface FileRoutesByTo {
'/': typeof IndexLazyRoute
'/get_address': typeof GetaddressLazyRoute
'/get_balance': typeof GetbalanceLazyRoute
'/get_balance_usdc': typeof GetbalanceusdcLazyRoute
'/get_batch_balances': typeof GetbatchbalancesLazyRoute
'/get_latest_block': typeof GetlatestblockLazyRoute
'/send_eth': typeof SendethLazyRoute
Expand All @@ -197,6 +214,7 @@ export interface FileRoutesById {
'/': typeof IndexLazyRoute
'/get_address': typeof GetaddressLazyRoute
'/get_balance': typeof GetbalanceLazyRoute
'/get_balance_usdc': typeof GetbalanceusdcLazyRoute
'/get_batch_balances': typeof GetbatchbalancesLazyRoute
'/get_latest_block': typeof GetlatestblockLazyRoute
'/send_eth': typeof SendethLazyRoute
Expand All @@ -212,6 +230,7 @@ export interface FileRouteTypes {
| '/'
| '/get_address'
| '/get_balance'
| '/get_balance_usdc'
| '/get_batch_balances'
| '/get_latest_block'
| '/send_eth'
Expand All @@ -224,6 +243,7 @@ export interface FileRouteTypes {
| '/'
| '/get_address'
| '/get_balance'
| '/get_balance_usdc'
| '/get_batch_balances'
| '/get_latest_block'
| '/send_eth'
Expand All @@ -236,6 +256,7 @@ export interface FileRouteTypes {
| '/'
| '/get_address'
| '/get_balance'
| '/get_balance_usdc'
| '/get_batch_balances'
| '/get_latest_block'
| '/send_eth'
Expand All @@ -250,6 +271,7 @@ export interface RootRouteChildren {
IndexLazyRoute: typeof IndexLazyRoute
GetaddressLazyRoute: typeof GetaddressLazyRoute
GetbalanceLazyRoute: typeof GetbalanceLazyRoute
GetbalanceusdcLazyRoute: typeof GetbalanceusdcLazyRoute
GetbatchbalancesLazyRoute: typeof GetbatchbalancesLazyRoute
GetlatestblockLazyRoute: typeof GetlatestblockLazyRoute
SendethLazyRoute: typeof SendethLazyRoute
Expand All @@ -263,6 +285,7 @@ const rootRouteChildren: RootRouteChildren = {
IndexLazyRoute: IndexLazyRoute,
GetaddressLazyRoute: GetaddressLazyRoute,
GetbalanceLazyRoute: GetbalanceLazyRoute,
GetbalanceusdcLazyRoute: GetbalanceusdcLazyRoute,
GetbatchbalancesLazyRoute: GetbatchbalancesLazyRoute,
GetlatestblockLazyRoute: GetlatestblockLazyRoute,
SendethLazyRoute: SendethLazyRoute,
Expand All @@ -287,6 +310,7 @@ export const routeTree = rootRoute
"/",
"/get_address",
"/get_balance",
"/get_balance_usdc",
"/get_batch_balances",
"/get_latest_block",
"/send_eth",
Expand All @@ -305,6 +329,9 @@ export const routeTree = rootRoute
"/get_balance": {
"filePath": "get_balance.lazy.tsx"
},
"/get_balance_usdc": {
"filePath": "get_balance_usdc.lazy.tsx"
},
"/get_batch_balances": {
"filePath": "get_batch_balances.lazy.tsx"
},
Expand Down
49 changes: 49 additions & 0 deletions src/frontend/routes/get_balance_usdc.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Link, createLazyFileRoute } from "@tanstack/react-router";

import { backend } from "../../backend/declarations";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import Source from "../components/source";
import Spinner from "../components/spinner";

export const Route = createLazyFileRoute("/get_balance_usdc")({
component: Page,
});

function Page() {
const [ethAddress, setEthAddress] = useState<string>("");

const {
data: accountBalanceResult,
isFetching: isFetchingAccountBalance,
refetch: refetchAccountBalance,
} = useQuery({
queryKey: ["get_balance_usdc", ethAddress],
queryFn: () => backend.get_balance_usdc([ethAddress]),
enabled: false,
});

return (
<>
<Link to="/">
<button> Menu</button>
</Link>
<div className="card">
<p>Request the USDC balance of an ETH account.</p>
<input
type="text"
placeholder="ETH address"
onChange={(e) => setEthAddress(e.target.value)}
value={ethAddress}
/>
<button disabled={isFetchingAccountBalance} onClick={() => void refetchAccountBalance()}>
{isFetchingAccountBalance ? <Spinner /> : "get_balance_usdc(ethAddress)"}
</button>
{accountBalanceResult && (
<pre>{JSON.stringify(accountBalanceResult, null, 2)}</pre>
)}
<Source file="get_balance_usdc.rs" />
</div>
</>
);
}
3 changes: 3 additions & 0 deletions src/frontend/routes/index.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function Index() {
<Link to="/get_balance">
<button>get_balance(address)</button>
</Link>
<Link to="/get_balance_usdc">
<button>get_balance_usdc(address)</button>
</Link>
<Link to="/get_batch_balances">
<button>get_batch_balances([address1, address2])</button>
</Link>
Expand Down

0 comments on commit a3fb927

Please sign in to comment.