@devvmichael/create-stacks-app 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devvmichael/create-stacks-app",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Scaffold full-stack Stacks blockchain applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,31 +1,13 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import { ReactNode } from 'react';
4
- import { Connect } from '@stacks/connect-react';
5
- import { userSession } from '@/lib/stacks';
3
+ import { ReactNode } from "react";
6
4
 
7
5
  interface ProvidersProps {
8
6
  children: ReactNode;
9
7
  }
10
8
 
9
+ // With Stacks Connect v8, no provider wrapper is needed
10
+ // The connect() function handles wallet connection directly
11
11
  export function Providers({ children }: ProvidersProps) {
12
- const appDetails = {
13
- name: 'Stacks App',
14
- icon: typeof window !== 'undefined' ? window.location.origin + '/logo.svg' : '/logo.svg',
15
- };
16
-
17
- return (
18
- <Connect
19
- authOptions={{
20
- appDetails,
21
- redirectTo: '/',
22
- onFinish: () => {
23
- window.location.reload();
24
- },
25
- userSession,
26
- }}
27
- >
28
- {children}
29
- </Connect>
30
- );
12
+ return <>{children}</>;
31
13
  }
@@ -1,19 +1,9 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import { useConnect } from '@stacks/connect-react';
4
- import { useStacks } from '@/hooks/use-stacks';
3
+ import { useStacks } from "@/hooks/use-stacks";
5
4
 
6
5
  export function ConnectButton() {
7
- const { authenticate } = useConnect();
8
- const { userSession, address, isLoading } = useStacks();
9
-
10
- const handleConnect = () => {
11
- authenticate();
12
- };
13
-
14
- const handleDisconnect = () => {
15
- userSession.signUserOut('/');
16
- };
6
+ const { address, isLoading, isConnected, connect, disconnect } = useStacks();
17
7
 
18
8
  if (isLoading) {
19
9
  return (
@@ -23,13 +13,13 @@ export function ConnectButton() {
23
13
  );
24
14
  }
25
15
 
26
- if (address) {
16
+ if (isConnected && address) {
27
17
  return (
28
18
  <div className="flex items-center gap-3">
29
19
  <span className="text-sm bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded-full">
30
20
  {address.slice(0, 6)}...{address.slice(-4)}
31
21
  </span>
32
- <button onClick={handleDisconnect} className="btn-secondary text-sm">
22
+ <button onClick={disconnect} className="btn-secondary text-sm">
33
23
  Disconnect
34
24
  </button>
35
25
  </div>
@@ -37,7 +27,7 @@ export function ConnectButton() {
37
27
  }
38
28
 
39
29
  return (
40
- <button onClick={handleConnect} className="btn-primary">
30
+ <button onClick={connect} className="btn-primary">
41
31
  Connect Wallet
42
32
  </button>
43
33
  );
@@ -1,11 +1,14 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import { useState } from 'react';
4
- import { openContractCall } from '@stacks/connect';
5
- import { useStacks } from './use-stacks';
6
- import type { ContractConfig } from '@/lib/contracts';
3
+ import { useState } from "react";
4
+ import { request } from "@/lib/stacks";
5
+ import { useStacks } from "./use-stacks";
6
+ import type { ContractConfig } from "@/lib/contracts";
7
7
 
8
- export function useContractCall(contract: ContractConfig, functionName: string) {
8
+ export function useContractCall(
9
+ contract: ContractConfig,
10
+ functionName: string,
11
+ ) {
9
12
  const [isLoading, setIsLoading] = useState(false);
10
13
  const [error, setError] = useState<Error | null>(null);
11
14
  const [txId, setTxId] = useState<string | null>(null);
@@ -13,28 +16,26 @@ export function useContractCall(contract: ContractConfig, functionName: string)
13
16
 
14
17
  const call = async (functionArgs: any[] = []) => {
15
18
  if (!address) {
16
- throw new Error('Wallet not connected');
19
+ throw new Error("Wallet not connected");
17
20
  }
18
21
 
19
22
  setIsLoading(true);
20
23
  setError(null);
21
24
 
22
25
  try {
23
- await openContractCall({
24
- contractAddress: contract.address,
25
- contractName: contract.name,
26
+ // Using Stacks Connect v8 request API
27
+ const result = await request("stx_callContract", {
28
+ contract: `${contract.address}.${contract.name}`,
26
29
  functionName,
27
30
  functionArgs,
28
- network: contract.network,
29
- postConditions: [],
30
- onFinish: (data) => {
31
- setTxId(data.txId);
32
- console.log('Transaction submitted:', data.txId);
33
- },
34
- onCancel: () => {
35
- setIsLoading(false);
36
- },
37
31
  });
32
+
33
+ if (result?.txId) {
34
+ setTxId(result.txId);
35
+ console.log("Transaction submitted:", result.txId);
36
+ }
37
+
38
+ return result;
38
39
  } catch (err) {
39
40
  setError(err as Error);
40
41
  throw err;
@@ -1,26 +1,49 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
- import { useEffect, useState } from 'react';
4
- import { userSession } from '@/lib/stacks';
3
+ import { useEffect, useState, useCallback } from "react";
4
+ import {
5
+ getConnectedAddress,
6
+ checkIsConnected,
7
+ connectWallet,
8
+ disconnectWallet,
9
+ } from "@/lib/stacks";
5
10
 
6
11
  export function useStacks() {
7
12
  const [address, setAddress] = useState<string | null>(null);
8
13
  const [isLoading, setIsLoading] = useState(true);
9
14
 
15
+ // Check connection status on mount
10
16
  useEffect(() => {
11
- if (userSession.isUserSignedIn()) {
12
- const userData = userSession.loadUserData();
13
- // Use testnet address by default, mainnet in production
14
- const network = process.env.NEXT_PUBLIC_NETWORK === 'mainnet' ? 'mainnet' : 'testnet';
15
- setAddress(userData.profile.stxAddress[network]);
16
- }
17
+ const connectedAddress = getConnectedAddress();
18
+ setAddress(connectedAddress);
19
+ setIsLoading(false);
20
+ }, []);
21
+
22
+ // Connect handler
23
+ const connect = useCallback(async () => {
24
+ setIsLoading(true);
25
+ const connectedAddress = await connectWallet();
26
+ setAddress(connectedAddress);
17
27
  setIsLoading(false);
28
+
29
+ // Reload to sync state
30
+ if (connectedAddress) {
31
+ window.location.reload();
32
+ }
33
+ }, []);
34
+
35
+ // Disconnect handler
36
+ const disconnect = useCallback(() => {
37
+ disconnectWallet();
38
+ setAddress(null);
39
+ window.location.reload();
18
40
  }, []);
19
41
 
20
42
  return {
21
- userSession,
22
43
  address,
23
44
  isLoading,
24
- isConnected: !!address,
45
+ isConnected: !!address && checkIsConnected(),
46
+ connect,
47
+ disconnect,
25
48
  };
26
49
  }
@@ -1,5 +1,5 @@
1
- import { network } from './stacks';
2
- import type { StacksNetwork } from '@stacks/network';
1
+ import { network } from "./stacks";
2
+ import type { StacksNetwork } from "@stacks/network";
3
3
 
4
4
  export interface ContractConfig {
5
5
  address: string;
@@ -8,22 +8,24 @@ export interface ContractConfig {
8
8
  }
9
9
 
10
10
  // Contract address from environment or default devnet address
11
- const contractAddress = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS || 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM';
11
+ const contractAddress =
12
+ process.env.NEXT_PUBLIC_CONTRACT_ADDRESS ||
13
+ "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM";
12
14
 
13
15
  export const counterContract: ContractConfig = {
14
16
  address: contractAddress,
15
- name: 'counter',
17
+ name: "counter",
16
18
  network,
17
19
  };
18
20
 
19
21
  export const tokenContract: ContractConfig = {
20
22
  address: contractAddress,
21
- name: 'token',
23
+ name: "token",
22
24
  network,
23
25
  };
24
26
 
25
27
  export const nftContract: ContractConfig = {
26
28
  address: contractAddress,
27
- name: 'nft',
29
+ name: "nft",
28
30
  network,
29
31
  };
@@ -1,18 +1,57 @@
1
- import { AppConfig, UserSession } from '@stacks/connect';
2
- import { StacksTestnet, StacksMainnet } from '@stacks/network';
3
-
4
- const appConfig = new AppConfig(['store_write', 'publish_data']);
5
- export const userSession = new UserSession({ appConfig });
1
+ import {
2
+ connect,
3
+ disconnect,
4
+ isConnected,
5
+ getLocalStorage,
6
+ request,
7
+ } from "@stacks/connect";
8
+ import { STACKS_TESTNET, STACKS_MAINNET } from "@stacks/network";
6
9
 
10
+ // Network configuration
7
11
  export const network =
8
- process.env.NEXT_PUBLIC_NETWORK === 'mainnet'
9
- ? new StacksMainnet()
10
- : new StacksTestnet();
12
+ process.env.NEXT_PUBLIC_NETWORK === "mainnet"
13
+ ? STACKS_MAINNET
14
+ : STACKS_TESTNET;
15
+
16
+ // Get the connected user's address from local storage
17
+ export function getConnectedAddress(): string | null {
18
+ const storage = getLocalStorage();
19
+ if (!storage) return null;
20
+
21
+ const networkType =
22
+ process.env.NEXT_PUBLIC_NETWORK === "mainnet" ? "mainnet" : "testnet";
23
+ return storage.addresses?.[networkType] || null;
24
+ }
25
+
26
+ // Check if user is connected
27
+ export function checkIsConnected(): boolean {
28
+ return isConnected();
29
+ }
11
30
 
31
+ // Connect wallet
32
+ export async function connectWallet(): Promise<string | null> {
33
+ try {
34
+ const response = await connect();
35
+ return response.addresses?.[0]?.address || null;
36
+ } catch (error) {
37
+ console.error("Failed to connect wallet:", error);
38
+ return null;
39
+ }
40
+ }
41
+
42
+ // Disconnect wallet
43
+ export function disconnectWallet(): void {
44
+ disconnect();
45
+ }
46
+
47
+ // Get explorer link
12
48
  export function getExplorerLink(txId: string): string {
13
49
  const baseUrl =
14
- process.env.NEXT_PUBLIC_NETWORK === 'mainnet'
15
- ? 'https://explorer.stacks.co'
16
- : 'https://explorer.stacks.co/?chain=testnet';
50
+ process.env.NEXT_PUBLIC_NETWORK === "mainnet"
51
+ ? "https://explorer.stacks.co"
52
+ : "https://explorer.stacks.co/?chain=testnet";
17
53
  return `${baseUrl}/txid/${txId}`;
18
54
  }
55
+
56
+ // Export request for contract calls
57
+ export { request };
@@ -10,7 +10,6 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@stacks/connect": "^8.2.4",
13
- "@stacks/connect-react": "^23.1.4",
14
13
  "@stacks/network": "^7.3.1",
15
14
  "@stacks/transactions": "^7.3.1",
16
15
  "next": "^14.2.21",