@devvmichael/create-stacks-app 0.2.1 → 0.2.3
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/dist/index.js +30 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/frontends/nextjs/template/app/providers.tsx +5 -23
- package/templates/frontends/nextjs/template/components/wallet/connect-button.tsx +6 -16
- package/templates/frontends/nextjs/template/hooks/use-contract-call.ts +20 -19
- package/templates/frontends/nextjs/template/hooks/use-stacks.ts +34 -11
- package/templates/frontends/nextjs/template/lib/contracts.ts +8 -6
- package/templates/frontends/nextjs/template/lib/stacks.ts +50 -11
- package/templates/frontends/nextjs/template/package.json +0 -1
package/dist/index.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from
|
|
3
|
-
import { createCommand } from
|
|
4
|
-
import { addCommand } from
|
|
5
|
-
import { deployCommand } from
|
|
6
|
-
import { readFileSync } from
|
|
7
|
-
import { fileURLToPath } from
|
|
8
|
-
import { dirname, join } from
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { createCommand } from "./commands/create.js";
|
|
4
|
+
import { addCommand } from "./commands/add.js";
|
|
5
|
+
import { deployCommand } from "./commands/deploy.js";
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { dirname, join } from "path";
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = dirname(__filename);
|
|
11
|
-
const packageJsonPath = join(__dirname,
|
|
12
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath,
|
|
11
|
+
const packageJsonPath = join(__dirname, "..", "package.json");
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
13
13
|
const program = new Command();
|
|
14
14
|
program
|
|
15
|
-
.name(
|
|
16
|
-
.description(
|
|
15
|
+
.name("create-stacks-app")
|
|
16
|
+
.description("Scaffold full-stack Stacks blockchain applications")
|
|
17
17
|
.version(packageJson.version);
|
|
18
18
|
// Main create command (default)
|
|
19
19
|
program
|
|
20
|
-
.argument(
|
|
21
|
-
.option(
|
|
22
|
-
.option(
|
|
23
|
-
.option(
|
|
24
|
-
.option(
|
|
25
|
-
.option(
|
|
26
|
-
.option(
|
|
27
|
-
.option(
|
|
28
|
-
.option(
|
|
29
|
-
.option(
|
|
30
|
-
.option(
|
|
20
|
+
.argument("[project-name]", "Name of the project")
|
|
21
|
+
.option("-t, --template <name>", "Template to use (nextjs, react, vue)")
|
|
22
|
+
.option("-c, --contracts <list>", "Contracts to include (counter,token,nft)")
|
|
23
|
+
.option("--typescript", "Use TypeScript")
|
|
24
|
+
.option("--no-typescript", "Use JavaScript")
|
|
25
|
+
.option("--tailwind", "Include Tailwind CSS")
|
|
26
|
+
.option("--no-tailwind", "Skip Tailwind CSS")
|
|
27
|
+
.option("--no-git", "Skip Git initialization")
|
|
28
|
+
.option("--package-manager <pm>", "Package manager (npm, pnpm, yarn)")
|
|
29
|
+
.option("--skip-install", "Skip dependency installation")
|
|
30
|
+
.option("-y, --yes", "Skip prompts, use defaults")
|
|
31
31
|
.action(createCommand);
|
|
32
32
|
// Add command for contracts and components
|
|
33
33
|
program
|
|
34
|
-
.command(
|
|
35
|
-
.description(
|
|
36
|
-
.option(
|
|
37
|
-
.option(
|
|
38
|
-
.option(
|
|
34
|
+
.command("add <type> <name>")
|
|
35
|
+
.description("Add a contract or component to existing project")
|
|
36
|
+
.option("--sip010", "Create a SIP-010 fungible token contract")
|
|
37
|
+
.option("--sip009", "Create a SIP-009 NFT contract")
|
|
38
|
+
.option("-t, --template <name>", "Use a specific template (e.g. marketplace, defi)")
|
|
39
39
|
.action(addCommand);
|
|
40
40
|
// Deploy command
|
|
41
41
|
program
|
|
42
|
-
.command(
|
|
43
|
-
.description(
|
|
44
|
-
.option(
|
|
42
|
+
.command("deploy <network>")
|
|
43
|
+
.description("Deploy contracts to testnet or mainnet")
|
|
44
|
+
.option("--private-key <key>", "Private key for deployment (or use env var)")
|
|
45
45
|
.action(deployCommand);
|
|
46
46
|
program.parse();
|
|
47
47
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,mBAAmB,CAAC;KACzB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,gCAAgC;AAChC,OAAO;KACJ,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KACjD,MAAM,CAAC,uBAAuB,EAAE,sCAAsC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,mBAAmB,CAAC;KACzB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,gCAAgC;AAChC,OAAO;KACJ,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KACjD,MAAM,CAAC,uBAAuB,EAAE,sCAAsC,CAAC;KACvE,MAAM,CAAC,wBAAwB,EAAE,0CAA0C,CAAC;KAC5E,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC;KACxC,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,sBAAsB,CAAC;KAC5C,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC;KAC5C,MAAM,CAAC,UAAU,EAAE,yBAAyB,CAAC;KAC7C,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,gBAAgB,EAAE,8BAA8B,CAAC;KACxD,MAAM,CAAC,WAAW,EAAE,4BAA4B,CAAC;KACjD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,2CAA2C;AAC3C,OAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,UAAU,EAAE,0CAA0C,CAAC;KAC9D,MAAM,CAAC,UAAU,EAAE,+BAA+B,CAAC;KACnD,MAAM,CACL,uBAAuB,EACvB,kDAAkD,CACnD;KACA,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,iBAAiB;AACjB,OAAO;KACJ,OAAO,CAAC,kBAAkB,CAAC;KAC3B,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,qBAAqB,EAAE,6CAA6C,CAAC;KAC5E,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,31 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import { ReactNode } from
|
|
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
|
-
|
|
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
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { useStacks } from '@/hooks/use-stacks';
|
|
3
|
+
import { useStacks } from "@/hooks/use-stacks";
|
|
5
4
|
|
|
6
5
|
export function ConnectButton() {
|
|
7
|
-
const {
|
|
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={
|
|
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={
|
|
30
|
+
<button onClick={connect} className="btn-primary">
|
|
41
31
|
Connect Wallet
|
|
42
32
|
</button>
|
|
43
33
|
);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState } from
|
|
4
|
-
import {
|
|
5
|
-
import { useStacks } from
|
|
6
|
-
import type { ContractConfig } from
|
|
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(
|
|
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(
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useState } from
|
|
4
|
-
import {
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
2
|
-
import type { StacksNetwork } from
|
|
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 =
|
|
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:
|
|
17
|
+
name: "counter",
|
|
16
18
|
network,
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
export const tokenContract: ContractConfig = {
|
|
20
22
|
address: contractAddress,
|
|
21
|
-
name:
|
|
23
|
+
name: "token",
|
|
22
24
|
network,
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
export const nftContract: ContractConfig = {
|
|
26
28
|
address: contractAddress,
|
|
27
|
-
name:
|
|
29
|
+
name: "nft",
|
|
28
30
|
network,
|
|
29
31
|
};
|
|
@@ -1,18 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 ===
|
|
9
|
-
?
|
|
10
|
-
:
|
|
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 ===
|
|
15
|
-
?
|
|
16
|
-
:
|
|
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 };
|