Skip to content

Commit

Permalink
docs: update starknetkit demo for experiment (#480)
Browse files Browse the repository at this point in the history
this updates the starknetkit demo to experiment with web and mobile
based wallets
  • Loading branch information
fracek authored Aug 18, 2024
2 parents a950d18 + 231bb42 commit 852f202
Show file tree
Hide file tree
Showing 8 changed files with 4,323 additions and 5,478 deletions.
147 changes: 91 additions & 56 deletions docs/components/demo/starknetkit.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import {
type Connector,
useAccount,
publicProvider,
StarknetConfig,
useConnect,
useContract,
useNetwork,
useSendTransaction,
} from "@starknet-react/core";
import { DemoContainer } from "../starknet";
import {
type StarknetkitConnector,
useStarknetkitConnectModal,
} from "starknetkit";
import type { Abi } from "starknet";
import { availableConnectors } from "../starknetkit";
import { mainnet, sepolia } from "@starknet-react/chains";
import { useState } from "react";

export function StarknetKit() {
return (
<DemoContainer>
<StarknetProvider>
<StarknetKitInner />
</DemoContainer>
</StarknetProvider>
);
}

/** This Demo is for experimental purpose only, will be removed later */
function StarknetKitInner() {
const { connectAsync, connectors } = useConnect();
const { starknetkitConnectModal } = useStarknetkitConnectModal({
connectors: connectors as StarknetkitConnector[],
connectors: availableConnectors as StarknetkitConnector[],
});

const connectWallet = async () => {
Expand All @@ -35,59 +35,94 @@ function StarknetKitInner() {
await connectAsync({ connector: connector as Connector });
};

const { address } = useAccount();
return (
<div>
<div className="flex flex-col gap-4">
{connectors.map((connector, index) => (
<WalletButton connector={connector} key={connector.id} />
))}

const { chain } = useNetwork();
const { contract } = useContract({
abi,
address: chain.nativeCurrency.address,
});
<div className="my-5"> Starknetkit Modal</div>
<button onClick={connectWallet} className="button">
Starknetkit Modal
</button>
</div>
</div>
);
}

const { isError, error, send } = useSendTransaction({
calls:
contract && address
? [contract.populate("transfer", [address, 1n])]
: undefined,
});
function WalletButton({ connector }: { connector: Connector }) {
const [res, setRes] = useState<string>("-- No res --");
const [res2, setRes2] = useState<string>("-- No res --");
const [res3, setRes3] = useState<string>("-- No res --");

const [time1, setTime1] = useState<number | undefined>(undefined);
const [time2, setTime2] = useState<number | undefined>(undefined);

async function connectWallet() {
const _res = await connector.connect();
setRes(JSON.stringify(_res.account));
}

async function request() {
const start = performance.now();
const _res = await connector.request({
type: "wallet_getPermissions",
});
const end = performance.now();
setTime1(end - start);
setRes2(JSON.stringify(_res));
}

async function request2() {
const start = performance.now();
const _res = await connector.request({
type: "wallet_requestAccounts",
params: { silent_mode: true },
});
const end = performance.now();
setTime2(end - start);
setRes3(JSON.stringify(_res));
}

return (
<div>
{address ? (
<>
<p>
<span className="font-bold"> Connected Account: </span> {address}
</p>
<div>
<button onClick={() => send()} className="button">
Send Transaction
</button>
{isError && <p>Error: {error?.message}</p>}
</div>
</>
) : (
<button onClick={connectWallet} className="button">
Connect Starknet Wallet (StarknetKit)
<div className="my-4 flex flex-col gap-2">
<button onClick={() => connectWallet()} className="button">
{connector.id} | connect()
<br />
{res}
</button>
<div className="flex gap-4">
<button onClick={() => request()} className="button !bg-red-900">
Request Call (wallet_getPermissions)
<br />
{res2}
{time1 && <div>Time: {Math.floor(time1)} ms</div>}
</button>
)}
<button onClick={() => request2()} className="button !bg-red-900">
Request Call (wallet_requestAccounts with silent_mode)
<br />
{res3}
{time2 && <div>Time: {Math.floor(time2)} ms</div>}
</button>
</div>
</div>
);
}

const abi = [
{
type: "function",
name: "transfer",
state_mutability: "external",
inputs: [
{
name: "recipient",
type: "core::starknet::contract_address::ContractAddress",
},
{
name: "amount",
type: "core::integer::u256",
},
],
outputs: [],
},
] as const satisfies Abi;
function StarknetProvider({ children }: { children: React.ReactNode }) {
const chains = [sepolia, mainnet];
const provider = publicProvider();

return (
<StarknetConfig
chains={chains}
provider={provider}
connectors={availableConnectors}
>
<div className="flex flex-col border border-red-500 rounded shadow-md">
<div className="p-4">{children}</div>
</div>
</StarknetConfig>
);
}
1 change: 1 addition & 0 deletions docs/components/starknetkit/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./starknetkit-connectors";
30 changes: 30 additions & 0 deletions docs/components/starknetkit/starknetkit-connectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { constants } from "starknet";
import {
isInArgentMobileAppBrowser,
ArgentMobileConnector,
} from "starknetkit/argentMobile";
import { InjectedConnector } from "starknetkit/injected";
import { WebWalletConnector } from "starknetkit/webwallet";

export const availableConnectors = isInArgentMobileAppBrowser()
? [
ArgentMobileConnector.init({
options: {
url: typeof window !== "undefined" ? window.location.href : "",
dappName: "Example dapp",
chainId: constants.NetworkName.SN_SEPOLIA,
},
}),
]
: [
new InjectedConnector({ options: { id: "argentX" } }),
new InjectedConnector({ options: { id: "braavos" } }),
ArgentMobileConnector.init({
options: {
url: typeof window !== "undefined" ? window.location.href : "",
dappName: "Example dapp",
chainId: constants.NetworkName.SN_SEPOLIA,
},
}),
new WebWalletConnector({ url: "https://web.argent.xyz" }),
];
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@starknet-react/core": "workspace:*",
"react": "^18.2.0",
"starknet": "^6.12.1",
"starknetkit": "^2.2.16",
"starknetkit": "^2.2.24",
"vocs": "1.0.0-alpha.53"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/demo/starknetkit.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Demo from "../../components/demo";

# StarknetKit Integration
# StarknetKit Integration (Experimental)

<Demo.StarknetKit />
23 changes: 17 additions & 6 deletions docs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
{
"extends": "@starknet-react/typescript-config/react-library.json",
"compilerOptions": {
"noEmit": true
},
"include": ["components"]
"extends": "@starknet-react/typescript-config/react-library.json",
"compilerOptions": {
"noEmit": true,
"target": "es2020",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["components"]
}

11 changes: 11 additions & 0 deletions packages/core/src/hooks/use-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { AccountInterface } from "starknet";
import type { Connector } from "../connectors";
import { useStarknetAccount } from "../context/account";

import { Permission } from "@starknet-io/types-js";
import { useConnect } from "./use-connect";

/** Account connection status. */
Expand Down Expand Up @@ -68,6 +69,16 @@ export function useAccount(): UseAccountResult {
// If the account is connected, we get the address
let connAccount: string[] | undefined;
try {
// we get permissions from the wallet
const permissions: Permission[] = await connector.request({
type: "wallet_getPermissions",
});

// if the wallet doesn't have the permission to get accounts,
// that means the wallet is not connected and we skip it
if (!permissions.includes(Permission.ACCOUNTS)) continue;

// if the wallet is connected and has permissions, so we request the accounts
connAccount = await connector.request({
type: "wallet_requestAccounts",
params: { silent_mode: true },
Expand Down
Loading

0 comments on commit 852f202

Please sign in to comment.