From 79611223ea715f691ad53b320cb84f8b2edeb381 Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Thu, 22 Feb 2024 20:16:27 +0300 Subject: [PATCH] Refactor React components and update dependencies --- examples/react-provider/src/AddNote.tsx | 5 +- examples/react-provider/src/App.tsx | 43 +-- examples/react-provider/src/IcpBalance.tsx | 29 ++ examples/react-provider/src/IcpTransfer.tsx | 62 ++++ examples/react-provider/src/Login.tsx | 9 +- examples/react-provider/src/NoteActor.ts | 12 + examples/react-provider/src/Notes.tsx | 5 +- .../src/declarations/icp-ledger.ts | 296 ++++++++++++++++++ 8 files changed, 422 insertions(+), 39 deletions(-) create mode 100644 examples/react-provider/src/IcpBalance.tsx create mode 100644 examples/react-provider/src/IcpTransfer.tsx create mode 100644 examples/react-provider/src/NoteActor.ts create mode 100644 examples/react-provider/src/declarations/icp-ledger.ts diff --git a/examples/react-provider/src/AddNote.tsx b/examples/react-provider/src/AddNote.tsx index e589ee47aa..b5e13b48cb 100644 --- a/examples/react-provider/src/AddNote.tsx +++ b/examples/react-provider/src/AddNote.tsx @@ -1,5 +1,4 @@ -import { useUpdateCall } from "@ic-reactor/react" -import { Backend } from "App" +import { useNoteUpdateCall } from "NoteActor" import { useState } from "react" interface AddNoteProps { @@ -9,7 +8,7 @@ interface AddNoteProps { const AddNote: React.FC = ({ publicKey }) => { const [input, setInput] = useState("") - const { call, data, loading, error } = useUpdateCall({ + const { call, data, loading, error } = useNoteUpdateCall({ functionName: "add_simple_note", args: [publicKey, input], }) diff --git a/examples/react-provider/src/App.tsx b/examples/react-provider/src/App.tsx index 6ed2de02cc..9c08f70f22 100644 --- a/examples/react-provider/src/App.tsx +++ b/examples/react-provider/src/App.tsx @@ -1,52 +1,31 @@ import Login from "Login" import Notes from "Notes" import AddNote from "./AddNote" -import { backend } from "declarations/candid" -import { AgentProvider, ActorProvider, useQueryCall } from "@ic-reactor/react" +import { AgentProvider, ActorProvider } from "@ic-reactor/react" +import { NoteActorProvider } from "NoteActor" +import { ICPLedger } from "IcpBalance" +import { ICPTransfer } from "IcpTransfer" const publicKey = crypto.getRandomValues(new Uint8Array(48)) -export type Backend = typeof backend - const App = () => { return ( {/* idlFactory can be fetched from the network if you not provide it */} - + Loading Icp Ledger...} + > + - + Loading Note Actor...}> - + ) } export default App - -const ICPLedger = () => { - const { call, data, loading, error } = useQueryCall({ - functionName: "name", - }) - - return ( -
-

Test:

-
- Loading: {loading.toString()} -
- Error: {error?.toString()} -
- Data:{" "} - {data - ? JSON.stringify(data, (_, v) => - typeof v === "bigint" ? v.toString() : v - ) - : null} -
- -
- ) -} diff --git a/examples/react-provider/src/IcpBalance.tsx b/examples/react-provider/src/IcpBalance.tsx new file mode 100644 index 0000000000..f88aabc166 --- /dev/null +++ b/examples/react-provider/src/IcpBalance.tsx @@ -0,0 +1,29 @@ +import { useQueryCall, useUserPrincipal } from "@ic-reactor/react" + +export const ICPLedger = () => { + const principal = useUserPrincipal() + + const { call, data, loading, error } = useQueryCall({ + functionName: "icrc1_balance_of", + args: [{ owner: principal, subaccount: [] }], + }) + + return ( +
+

ICP Balance:

+
+ Loading: {loading.toString()} +
+ Error: {error?.toString()} +
+ balance:{" "} + {data !== undefined + ? JSON.stringify(data, (_, v) => + typeof v === "bigint" ? v.toString() : v + ) + : null} +
+ +
+ ) +} diff --git a/examples/react-provider/src/IcpTransfer.tsx b/examples/react-provider/src/IcpTransfer.tsx new file mode 100644 index 0000000000..7fe43de759 --- /dev/null +++ b/examples/react-provider/src/IcpTransfer.tsx @@ -0,0 +1,62 @@ +import { Principal } from "@dfinity/principal" +import { useUpdateCall } from "@ic-reactor/react" +import { useState } from "react" + +export const ICPTransfer = () => { + const [principal, setPrincipal] = useState("") + const [amount, setAmount] = useState("") + + const { call, data, loading, error } = useUpdateCall({ + functionName: "icrc1_transfer", + }) + + const onSubmit = (event: React.FormEvent) => { + event.preventDefault() + call([ + { + to: { + owner: Principal.fromText(principal), + subaccount: [], + }, + amount: BigInt(amount), + fee: [], + memo: [], + created_at_time: [], + from_subaccount: [], + }, + ]) + } + + return ( +
+

Transfer:

+
+ Loading: {loading.toString()} +
+ Error: {error?.toString()} +
+ response:{" "} + {data + ? JSON.stringify(data, (_, v) => + typeof v === "bigint" ? v.toString() : v + ) + : null} +
+
+ setPrincipal(e.target.value)} + /> + setAmount(e.target.value)} + /> + +
+
+ ) +} diff --git a/examples/react-provider/src/Login.tsx b/examples/react-provider/src/Login.tsx index 4052d0e584..01961aab98 100644 --- a/examples/react-provider/src/Login.tsx +++ b/examples/react-provider/src/Login.tsx @@ -67,7 +67,14 @@ const Login = () => { ) : (
-
diff --git a/examples/react-provider/src/NoteActor.ts b/examples/react-provider/src/NoteActor.ts new file mode 100644 index 0000000000..38f9daa2bb --- /dev/null +++ b/examples/react-provider/src/NoteActor.ts @@ -0,0 +1,12 @@ +import { createActorContext } from "@ic-reactor/react" +import { backend } from "declarations/candid" + +export type Backend = typeof backend + +export const { + ActorProvider: NoteActorProvider, + useQueryCall: useNoteQueryCall, + useUpdateCall: useNoteUpdateCall, +} = createActorContext({ + canisterId: "xeka7-ryaaa-aaaal-qb57a-cai", +}) diff --git a/examples/react-provider/src/Notes.tsx b/examples/react-provider/src/Notes.tsx index 66764564e4..38598a572a 100644 --- a/examples/react-provider/src/Notes.tsx +++ b/examples/react-provider/src/Notes.tsx @@ -1,12 +1,11 @@ -import { useQueryCall } from "@ic-reactor/react" -import { Backend } from "App" +import { useNoteQueryCall } from "NoteActor" interface NoteProps { publicKey: Uint8Array } const Notes: React.FC = ({ publicKey }) => { - const { call, data, loading, error } = useQueryCall({ + const { call, data, loading, error } = useNoteQueryCall({ functionName: "user_simple_notes", args: [publicKey], refetchInterval: 10000, diff --git a/examples/react-provider/src/declarations/icp-ledger.ts b/examples/react-provider/src/declarations/icp-ledger.ts new file mode 100644 index 0000000000..0e7ab35172 --- /dev/null +++ b/examples/react-provider/src/declarations/icp-ledger.ts @@ -0,0 +1,296 @@ +import type { Principal } from '@dfinity/principal'; +import type { ActorMethod } from '@dfinity/agent'; + +export interface Account { + owner: Principal; + subaccount: [] | [Uint8Array | number[]]; +} +export interface AccountBalanceArgs { + account: string; +} +export interface Allowance { + allowance: bigint; + expires_at: [] | [bigint]; +} +export interface AllowanceArgs { + account: Account; + spender: Account; +} +export interface ApproveArgs { + fee: [] | [bigint]; + memo: [] | [Uint8Array | number[]]; + from_subaccount: [] | [Uint8Array | number[]]; + created_at_time: [] | [bigint]; + amount: bigint; + expected_allowance: [] | [bigint]; + expires_at: [] | [bigint]; + spender: Account; +} +export type ApproveError = + | { + GenericError: { message: string; error_code: bigint }; + } + | { TemporarilyUnavailable: null } + | { Duplicate: { duplicate_of: bigint } } + | { BadFee: { expected_fee: bigint } } + | { AllowanceChanged: { current_allowance: bigint } } + | { CreatedInFuture: { ledger_time: bigint } } + | { TooOld: null } + | { Expired: { ledger_time: bigint } } + | { InsufficientFunds: { balance: bigint } }; +export interface ArchiveInfo { + canister_id: Principal; +} +export interface ArchiveOptions { + num_blocks_to_archive: bigint; + max_transactions_per_response: [] | [bigint]; + trigger_threshold: bigint; + max_message_size_bytes: [] | [bigint]; + cycles_for_archive_creation: [] | [bigint]; + node_max_memory_size_bytes: [] | [bigint]; + controller_id: Principal; +} +export interface ArchivedBlocksRange { + callback: [Principal, string]; + start: bigint; + length: bigint; +} +export interface ArchivedEncodedBlocksRange { + callback: [Principal, string]; + start: bigint; + length: bigint; +} +export interface Archives { + archives: Array; +} +export interface BinaryAccountBalanceArgs { + account: Uint8Array | number[]; +} +export interface BlockRange { + blocks: Array; +} +export interface CandidBlock { + transaction: CandidTransaction; + timestamp: TimeStamp; + parent_hash: [] | [Uint8Array | number[]]; +} +export type CandidOperation = + | { + Approve: { + fee: Tokens; + from: Uint8Array | number[]; + allowance_e8s: bigint; + allowance: Tokens; + expected_allowance: [] | [Tokens]; + expires_at: [] | [TimeStamp]; + spender: Uint8Array | number[]; + }; + } + | { + Burn: { + from: Uint8Array | number[]; + amount: Tokens; + spender: [] | [Uint8Array | number[]]; + }; + } + | { Mint: { to: Uint8Array | number[]; amount: Tokens } } + | { + Transfer: { + to: Uint8Array | number[]; + fee: Tokens; + from: Uint8Array | number[]; + amount: Tokens; + spender: [] | [Uint8Array | number[]]; + }; + }; +export interface CandidTransaction { + memo: bigint; + icrc1_memo: [] | [Uint8Array | number[]]; + operation: [] | [CandidOperation]; + created_at_time: TimeStamp; +} +export interface Decimals { + decimals: number; +} +export interface Duration { + secs: bigint; + nanos: number; +} +export interface FeatureFlags { + icrc2: boolean; +} +export interface GetBlocksArgs { + start: bigint; + length: bigint; +} +export type GetBlocksError = + | { + BadFirstBlockIndex: { + requested_index: bigint; + first_valid_index: bigint; + }; + } + | { Other: { error_message: string; error_code: bigint } }; +export interface InitArgs { + send_whitelist: Array; + token_symbol: [] | [string]; + transfer_fee: [] | [Tokens]; + minting_account: string; + maximum_number_of_accounts: [] | [bigint]; + accounts_overflow_trim_quantity: [] | [bigint]; + transaction_window: [] | [Duration]; + max_message_size_bytes: [] | [bigint]; + icrc1_minting_account: [] | [Account]; + archive_options: [] | [ArchiveOptions]; + initial_values: Array<[string, Tokens]>; + token_name: [] | [string]; + feature_flags: [] | [FeatureFlags]; +} +export type LedgerCanisterPayload = + | { Upgrade: [] | [UpgradeArgs] } + | { Init: InitArgs }; +export type MetadataValue = + | { Int: bigint } + | { Nat: bigint } + | { Blob: Uint8Array | number[] } + | { Text: string }; +export interface Name { + name: string; +} +export interface QueryBlocksResponse { + certificate: [] | [Uint8Array | number[]]; + blocks: Array; + chain_length: bigint; + first_block_index: bigint; + archived_blocks: Array; +} +export interface QueryEncodedBlocksResponse { + certificate: [] | [Uint8Array | number[]]; + blocks: Array; + chain_length: bigint; + first_block_index: bigint; + archived_blocks: Array; +} +export type Result = { Ok: bigint } | { Err: TransferError }; +export type Result_1 = { Ok: bigint } | { Err: ApproveError }; +export type Result_2 = { Ok: bigint } | { Err: TransferFromError }; +export type Result_3 = { Ok: BlockRange } | { Err: GetBlocksError }; +export type Result_4 = + | { Ok: Array } + | { Err: GetBlocksError }; +export type Result_5 = { Ok: bigint } | { Err: TransferError_1 }; +export interface SendArgs { + to: string; + fee: Tokens; + memo: bigint; + from_subaccount: [] | [Uint8Array | number[]]; + created_at_time: [] | [TimeStamp]; + amount: Tokens; +} +export interface StandardRecord { + url: string; + name: string; +} +export interface Symbol { + symbol: string; +} +export interface TimeStamp { + timestamp_nanos: bigint; +} +export interface Tokens { + e8s: bigint; +} +export interface TransferArg { + to: Account; + fee: [] | [bigint]; + memo: [] | [Uint8Array | number[]]; + from_subaccount: [] | [Uint8Array | number[]]; + created_at_time: [] | [bigint]; + amount: bigint; +} +export interface TransferArgs { + to: Uint8Array | number[]; + fee: Tokens; + memo: bigint; + from_subaccount: [] | [Uint8Array | number[]]; + created_at_time: [] | [TimeStamp]; + amount: Tokens; +} +export type TransferError = + | { + GenericError: { message: string; error_code: bigint }; + } + | { TemporarilyUnavailable: null } + | { BadBurn: { min_burn_amount: bigint } } + | { Duplicate: { duplicate_of: bigint } } + | { BadFee: { expected_fee: bigint } } + | { CreatedInFuture: { ledger_time: bigint } } + | { TooOld: null } + | { InsufficientFunds: { balance: bigint } }; +export type TransferError_1 = + | { + TxTooOld: { allowed_window_nanos: bigint }; + } + | { BadFee: { expected_fee: Tokens } } + | { TxDuplicate: { duplicate_of: bigint } } + | { TxCreatedInFuture: null } + | { InsufficientFunds: { balance: Tokens } }; +export interface TransferFee { + transfer_fee: Tokens; +} +export interface TransferFromArgs { + to: Account; + fee: [] | [bigint]; + spender_subaccount: [] | [Uint8Array | number[]]; + from: Account; + memo: [] | [Uint8Array | number[]]; + created_at_time: [] | [bigint]; + amount: bigint; +} +export type TransferFromError = + | { + GenericError: { message: string; error_code: bigint }; + } + | { TemporarilyUnavailable: null } + | { InsufficientAllowance: { allowance: bigint } } + | { BadBurn: { min_burn_amount: bigint } } + | { Duplicate: { duplicate_of: bigint } } + | { BadFee: { expected_fee: bigint } } + | { CreatedInFuture: { ledger_time: bigint } } + | { TooOld: null } + | { InsufficientFunds: { balance: bigint } }; +export interface UpgradeArgs { + maximum_number_of_accounts: [] | [bigint]; + icrc1_minting_account: [] | [Account]; + feature_flags: [] | [FeatureFlags]; +} +export interface _SERVICE { + account_balance: ActorMethod<[BinaryAccountBalanceArgs], Tokens>; + account_balance_dfx: ActorMethod<[AccountBalanceArgs], Tokens>; + account_identifier: ActorMethod<[Account], Uint8Array | number[]>; + archives: ActorMethod<[], Archives>; + decimals: ActorMethod<[], Decimals>; + icrc1_balance_of: ActorMethod<[Account], bigint>; + icrc1_decimals: ActorMethod<[], number>; + icrc1_fee: ActorMethod<[], bigint>; + icrc1_metadata: ActorMethod<[], Array<[string, MetadataValue]>>; + icrc1_minting_account: ActorMethod<[], [] | [Account]>; + icrc1_name: ActorMethod<[], string>; + icrc1_supported_standards: ActorMethod<[], Array>; + icrc1_symbol: ActorMethod<[], string>; + icrc1_total_supply: ActorMethod<[], bigint>; + icrc1_transfer: ActorMethod<[TransferArg], Result>; + icrc2_allowance: ActorMethod<[AllowanceArgs], Allowance>; + icrc2_approve: ActorMethod<[ApproveArgs], Result_1>; + icrc2_transfer_from: ActorMethod<[TransferFromArgs], Result_2>; + name: ActorMethod<[], Name>; + query_blocks: ActorMethod<[GetBlocksArgs], QueryBlocksResponse>; + query_encoded_blocks: ActorMethod< + [GetBlocksArgs], + QueryEncodedBlocksResponse + >; + send_dfx: ActorMethod<[SendArgs], bigint>; + symbol: ActorMethod<[], Symbol>; + transfer: ActorMethod<[TransferArgs], Result_5>; + transfer_fee: ActorMethod<[{}], TransferFee>; +}