# ONE Prompt ckUSDT wallet and payments in your caffeine App

**URL:** <https://forum.dfinity.org/t/one-prompt-ckusdt-wallet-and-payments-in-your-caffeine-app/61096>\
**Category:** Developers\
**Created:** [December 7, 2025, 9:37pm UTC](https://forum.dfinity.org/t/one-prompt-ckusdt-wallet-and-payments-in-your-caffeine-app/61096 "2025-12-07T21:37:10Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![WebTreeSoftwareSolut](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/webtreesoftwaresolut/32/35012_2.png) [@WebTreeSoftwareSolut](https://forum.dfinity.org/u/WebTreeSoftwareSolut)\
**Post date:** [December 7, 2025, 9:37pm UTC](https://forum.dfinity.org/t/one-prompt-ckusdt-wallet-and-payments-in-your-caffeine-app/61096/1 "2025-12-07T21:37:10Z")

</div>

[![r/ICPTrader - ONE PROMPT. ckUSDT wallet, Payments in your caffeine App|750xauto](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/3X/4/6/4695b329edc9e604c1fe0b19c36f6a63bf12d366.png)](https://preview.redd.it/one-prompt-ckusdt-wallet-payments-in-your-caffeine-app-v0-lufxb1ysou5g1.png?width=1199&format=png&auto=webp&s=b337aa88cacc764300cde963d8bf5b0266ecf43a)

> **[Web3 Console Application](https://proof-of-concept-vv0.caffeine.xyz/)**

Normally I would just post a link to my site [https://vibrew.app](https://vibrew.app/)

But this prompt is so fucking awesome I want all of you to have it, even the ones who don’t click the link.

**As usual, I take zero responsibility for anything this prompt does or fails to do. I do not endorse the management of user funds without an audit of your codebase done by a professional. Use what is presented here at your own risk and due diligence, I take responsibility for absolutely nothing.**

That being said here’s the prompt:

`This is a web 3 application.`

`The frontend must use agent host: "https://ic0.app"`

`Visitors can access the Web3 functionality of the app through the "Web 3 Console" that can be toggled on and off from the bottom of the screen. This console should be semi transparent.`

`This console allows 4 commands.`

`"login" command`

`initiates internet identity 2.0 authentication via "https://id.ai/authorize"`

`When the user is logged in their ckUSDT balance and principal id (icrc1 address) should be displayed in the upper right hand corner of the console. Clicking on the icrc1 address must copy it to the clipboard. Balance must auto update every 10 seconds. Balance must be displayed with 2 points of decimal precision.`

`The console ui must display an admin label, if the authenticated user is the admin.`

`"logout" command`

`Logs the user out of internet identity.`

`"send <principal> <value>" command`

`Sends ckUSDT to a valid icrc1 address (principal).`

`"make payment <value>" command`

`sends ckUSDT to the admin's principal`

`Avoid use of browser incompatible dependencies that require node, i.e. Buffer.`

`ckUSDT Token Functionality`

`1. Sending ckUSDT`

`Implement functionality for the user to send ckUSDT via the ledger canister ij33n-oiaaa-aaaar-qbooa-cai`

`2. Displaying Balance`

`To retrieve the balance, call the ledger canister method:`

`icrc1_balance_of : (record { owner: principal; subaccount: opt vec nat8 }) → (nat) query.`

`icrc1_decimals: () → (nat8) query`

`Do not include the optional subaccount parameter in icrc1_balance_of.`

`Use the returned nat value and convert it to ckUSDT by using conversion from icrc1_decimals.`

`Precision must not be lost`

`Use compatible types during:`

`ledger call`

`conversion`

`formatting`

`UI display`

`Balance Retrieval (pseudocode reference)`

`export function useGetTokenBalance(token: Token | null) {`

`const { identity } = useInternetIdentity();`

`return useQuery<bigint>({`

`queryKey: ['tokenBalance', token?.symbol, identity?.getPrincipal().toString()],`

`queryFn: async () => {`

`if (!identity || !token) throw new Error('Identity or token not available');`

`const account = createAccount(identity.getPrincipal());`

`// For ICP, use the index canister's icrc1_balance_of method`

`if (token.symbol === 'ICP' && token.index_canister_id) {`

`const indexActor = await createICPIndexActor(token.index_canister_id, identity);`

`const balance = await indexActor.icrc1_balance_of(account);`

`// Convert nat64 to bigint`

`return BigInt(balance.toString());`

`}`

`// For other tokens, use the ledger canister`

`const ledger = await createGenericLedgerActor(token.ledger_canister_id, identity);`

`const balance = await ledger.icrc1_balance_of(account);`

`// Return raw balance without normalization`

`return balance;`

`},`

`enabled: !!identity && !!token,`

`refetchInterval: 10000,`

`});`

`}`

`Summary of Requirements`

`Implement:`

`transfer functionality`

`balance retrieval with icrc1_balance_of()`

`Balance conversion`

`Display balance with 2-decimal precision`

`No precision loss in type handling or formatting`

`Before you begin, what questions do you have?`
