create-near-app 8.4.1 → 9.0.0

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.
Files changed (92) hide show
  1. package/dist/app.js +2 -1
  2. package/dist/make.js +7 -27
  3. package/dist/messages.js +1 -9
  4. package/dist/types.js +3 -2
  5. package/dist/user-input.js +32 -13
  6. package/dist/utils/index.js +1 -3
  7. package/package.json +2 -1
  8. package/templates/contracts/auction/rs/Cargo.toml +57 -0
  9. package/templates/contracts/auction/rs/README.md +39 -0
  10. package/templates/contracts/auction/rs/rust-toolchain.toml +4 -0
  11. package/templates/contracts/auction/rs/src/lib.rs +118 -0
  12. package/templates/contracts/auction/rs/tests/test_basics.rs +182 -0
  13. package/templates/contracts/auction/ts/README.md +47 -0
  14. package/templates/contracts/auction/ts/package.json +22 -0
  15. package/templates/contracts/auction/ts/sandbox-test/main.ava.js +88 -0
  16. package/templates/contracts/auction/ts/src/contract.ts +72 -0
  17. package/templates/contracts/auction/ts/tsconfig.json +14 -0
  18. package/templates/contracts/{rs → auction-adv/rs}/Cargo.toml +9 -7
  19. package/templates/contracts/auction-adv/rs/README.md +35 -0
  20. package/templates/contracts/{rs → auction-adv/rs}/rust-toolchain.toml +1 -1
  21. package/templates/contracts/auction-adv/rs/src/ext.rs +17 -0
  22. package/templates/contracts/auction-adv/rs/src/lib.rs +159 -0
  23. package/templates/contracts/auction-adv/rs/tests/fungible_token.wasm +0 -0
  24. package/templates/contracts/auction-adv/rs/tests/non_fungible_token.wasm +0 -0
  25. package/templates/contracts/auction-adv/rs/tests/test_basics.rs +430 -0
  26. package/templates/contracts/auction-adv/ts/README.md +45 -0
  27. package/templates/contracts/auction-adv/ts/package.json +22 -0
  28. package/templates/contracts/auction-adv/ts/sandbox-test/fungible_token.wasm +0 -0
  29. package/templates/contracts/auction-adv/ts/sandbox-test/main.ava.js +165 -0
  30. package/templates/contracts/auction-adv/ts/sandbox-test/non_fungible_token.wasm +0 -0
  31. package/templates/contracts/auction-adv/ts/src/contract.ts +87 -0
  32. package/templates/frontend/next-app/next-env.d.ts +6 -0
  33. package/templates/frontend/next-app/package.json +8 -22
  34. package/templates/frontend/{next-page/src/pages/hello-near/index.js → next-app/src/app/hello-near/page.tsx} +22 -21
  35. package/templates/frontend/next-app/src/app/layout.tsx +25 -0
  36. package/templates/frontend/next-app/src/components/{cards.js → cards.tsx} +4 -9
  37. package/templates/frontend/next-app/src/components/navigation.tsx +45 -0
  38. package/templates/frontend/next-app/tsconfig.json +42 -0
  39. package/templates/frontend/next-page/next-env.d.ts +6 -0
  40. package/templates/frontend/next-page/package.json +8 -22
  41. package/templates/frontend/next-page/src/components/{cards.js → cards.tsx} +0 -1
  42. package/templates/frontend/next-page/src/components/navigation.tsx +45 -0
  43. package/templates/frontend/next-page/src/pages/_app.tsx +15 -0
  44. package/templates/frontend/{vite-react/src/pages/hello_near.jsx → next-page/src/pages/hello-near/index.tsx} +18 -16
  45. package/templates/frontend/next-page/src/pages/{index.js → index.tsx} +8 -8
  46. package/templates/frontend/next-page/tsconfig.json +35 -0
  47. package/templates/frontend/vite-react/eslint.config.js +4 -1
  48. package/templates/frontend/vite-react/package.json +8 -25
  49. package/templates/frontend/vite-react/src/App.tsx +22 -0
  50. package/templates/frontend/vite-react/src/components/{cards.jsx → cards.tsx} +4 -4
  51. package/templates/frontend/vite-react/src/components/navigation.tsx +43 -0
  52. package/templates/frontend/vite-react/src/{config.js → config.ts} +1 -1
  53. package/templates/frontend/vite-react/src/global.d.ts +13 -0
  54. package/templates/frontend/vite-react/src/main.tsx +14 -0
  55. package/templates/frontend/vite-react/src/pages/hello_near.tsx +95 -0
  56. package/templates/frontend/vite-react/tsconfig.json +35 -0
  57. package/templates/contracts/py/.python-version +0 -1
  58. package/templates/contracts/py/README.md +0 -74
  59. package/templates/contracts/py/contract.py +0 -31
  60. package/templates/contracts/py/pyproject.toml +0 -10
  61. package/templates/contracts/py/tests/test_mod.py +0 -53
  62. package/templates/contracts/py/uv.lock +0 -878
  63. package/templates/contracts/rs/.github/workflows/deploy-production.yml +0 -25
  64. package/templates/contracts/rs/.github/workflows/deploy-staging.yml +0 -52
  65. package/templates/contracts/rs/.github/workflows/test.yml +0 -34
  66. package/templates/contracts/rs/.github/workflows/undeploy-staging.yml +0 -23
  67. package/templates/contracts/rs/README.md +0 -43
  68. package/templates/contracts/rs/src/lib.rs +0 -55
  69. package/templates/contracts/rs/tests/test_basics.rs +0 -30
  70. package/templates/contracts/ts/README.md +0 -83
  71. package/templates/contracts/ts/package.json +0 -23
  72. package/templates/contracts/ts/sandbox-test/main.ava.js +0 -45
  73. package/templates/contracts/ts/src/contract.ts +0 -23
  74. package/templates/contracts/ts/yarn.lock +0 -3290
  75. package/templates/frontend/next-app/jsconfig.json +0 -7
  76. package/templates/frontend/next-app/src/app/hello-near/page.js +0 -67
  77. package/templates/frontend/next-app/src/app/layout.js +0 -54
  78. package/templates/frontend/next-app/src/components/navigation.js +0 -35
  79. package/templates/frontend/next-app/src/wallets/web3modal.js +0 -27
  80. package/templates/frontend/next-page/jsconfig.json +0 -7
  81. package/templates/frontend/next-page/src/components/navigation.js +0 -35
  82. package/templates/frontend/next-page/src/pages/_app.js +0 -45
  83. package/templates/frontend/next-page/src/wallets/web3modal.js +0 -27
  84. package/templates/frontend/vite-react/src/App.jsx +0 -56
  85. package/templates/frontend/vite-react/src/components/navigation.jsx +0 -37
  86. package/templates/frontend/vite-react/src/main.jsx +0 -11
  87. package/templates/frontend/vite-react/src/wallets/web3modal.js +0 -27
  88. /package/templates/contracts/{ts → auction-adv/ts}/tsconfig.json +0 -0
  89. /package/templates/frontend/next-app/src/app/{page.js → page.tsx} +0 -0
  90. /package/templates/frontend/next-app/src/{config.js → config.ts} +0 -0
  91. /package/templates/frontend/next-page/src/{config.js → config.ts} +0 -0
  92. /package/templates/frontend/vite-react/src/pages/{home.jsx → home.tsx} +0 -0
@@ -0,0 +1,87 @@
1
+ // Find all our documentation at https://docs.near.org
2
+ import { NearBindgen, near, call, view, AccountId, NearPromise, initialize, assert } from "near-sdk-js";
3
+
4
+ class Bid {
5
+ bidder: AccountId;
6
+ bid: bigint;
7
+ }
8
+
9
+ const THIRTY_TGAS = BigInt("30000000000000");
10
+ const NO_DEPOSIT = BigInt(0);
11
+
12
+ @NearBindgen({ requireInit: true })
13
+ class AuctionContract {
14
+ highest_bid: Bid = { bidder: '', bid: BigInt(1) };
15
+ auction_end_time: bigint = BigInt(0);
16
+ auctioneer: AccountId = "";
17
+ claimed: boolean = false;
18
+ ft_contract: AccountId = "";
19
+ nft_contract: AccountId = "";
20
+ token_id: string = "";
21
+
22
+ @initialize({ privateFunction: true })
23
+ init({ end_time, auctioneer, ft_contract, nft_contract, token_id, starting_price }: { end_time: bigint, auctioneer: AccountId, ft_contract: AccountId, nft_contract: AccountId, token_id: string, starting_price: bigint }) {
24
+ this.auction_end_time = end_time;
25
+ this.highest_bid = { bidder: near.currentAccountId(), bid: starting_price };
26
+ this.auctioneer = auctioneer;
27
+ this.ft_contract = ft_contract;
28
+ this.nft_contract = nft_contract;
29
+ this.token_id = token_id;
30
+ }
31
+
32
+ @call({})
33
+ ft_on_transfer({ sender_id, amount, msg }: { sender_id: AccountId, amount: bigint, msg: String }) {
34
+
35
+ const previous = { ...this.highest_bid };
36
+
37
+ assert(this.auction_end_time > near.blockTimestamp(), "Auction has ended");
38
+ assert(near.predecessorAccountId() == this.ft_contract, "The token is not supported");
39
+ assert(BigInt(amount) >= BigInt(previous.bid), "You must place a higher bid");
40
+ this.highest_bid = {
41
+ bidder: sender_id,
42
+ bid: amount,
43
+ };
44
+
45
+ return NearPromise.new(this.ft_contract)
46
+ .functionCall("ft_transfer", JSON.stringify({ receiver_id: previous.bidder, amount: previous.bid }), BigInt(1), THIRTY_TGAS)
47
+ .then(
48
+ NearPromise.new(near.currentAccountId())
49
+ .functionCall("ft_transfer_callback", JSON.stringify({}), NO_DEPOSIT, THIRTY_TGAS)
50
+ )
51
+ .asReturn()
52
+ }
53
+
54
+ @call({})
55
+ claim() {
56
+ assert(this.auction_end_time <= near.blockTimestamp(), "Auction has not ended yet");
57
+ assert(!this.claimed, "Auction has been claimed");
58
+
59
+ this.claimed = true;
60
+
61
+ return NearPromise.new(this.nft_contract)
62
+ .functionCall("nft_transfer", JSON.stringify({ receiver_id: this.highest_bid.bidder, token_id: this.token_id }), BigInt(1), THIRTY_TGAS)
63
+ .then(NearPromise.new(this.ft_contract)
64
+ .functionCall("ft_transfer", JSON.stringify({ receiver_id: this.auctioneer, amount: this.highest_bid.bid }), BigInt(1), THIRTY_TGAS))
65
+ .asReturn()
66
+ }
67
+
68
+ @call({ privateFunction: true })
69
+ ft_transfer_callback({ }): BigInt {
70
+ return BigInt(0);
71
+ }
72
+
73
+ @view({})
74
+ get_highest_bid(): Bid {
75
+ return this.highest_bid;
76
+ }
77
+
78
+ @view({})
79
+ get_auction_end_time(): BigInt {
80
+ return this.auction_end_time;
81
+ }
82
+
83
+ @view({})
84
+ get_auction_info(): AuctionContract {
85
+ return this;
86
+ }
87
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -12,35 +12,21 @@
12
12
  "lint": "next lint"
13
13
  },
14
14
  "dependencies": {
15
- "@near-wallet-selector/bitte-wallet": "^9.0.2",
16
- "@near-wallet-selector/core": "^9.0.2",
17
- "@near-wallet-selector/ethereum-wallets": "^9.0.2",
18
- "@near-wallet-selector/here-wallet": "^9.0.2",
19
- "@near-wallet-selector/hot-wallet": "^9.0.2",
20
- "@near-wallet-selector/ledger": "^9.0.2",
21
- "@near-wallet-selector/meteor-wallet": "^9.0.2",
22
- "@near-wallet-selector/meteor-wallet-app": "^9.0.2",
23
- "@near-wallet-selector/modal-ui": "^9.0.2",
24
- "@near-wallet-selector/my-near-wallet": "^9.0.2",
25
- "@near-wallet-selector/near-mobile-wallet": "^9.0.2",
26
- "@near-wallet-selector/react-hook": "^9.0.2",
27
- "@near-wallet-selector/sender": "^9.0.2",
28
- "@near-wallet-selector/welldone-wallet": "^9.0.2",
29
- "@reown/appkit": "^1.7.7",
30
- "@reown/appkit-adapter-wagmi": "^1.7.7",
31
- "@wagmi/core": "^2.17.2",
32
15
  "bootstrap": "^5",
33
16
  "bootstrap-icons": "^1.11.3",
34
- "near-api-js": "^5.0.0",
17
+ "near-connect-hooks": "^1.0.2",
35
18
  "next": "^15",
36
19
  "react": "^18",
37
- "react-dom": "^18",
38
- "viem": "^2.30.5"
20
+ "react-dom": "^18"
39
21
  },
40
22
  "devDependencies": {
23
+ "@types/node": "^24.7.0",
24
+ "@types/react": "^19.2.2",
25
+ "@types/react-dom": "^19.2.1",
41
26
  "encoding": "^0.1.13",
42
27
  "eslint": "^9",
43
28
  "eslint-config-next": "^15",
44
- "pino-pretty": "^11.2.2"
29
+ "pino-pretty": "^11.2.2",
30
+ "typescript": "^5.9.3"
45
31
  }
46
- }
32
+ }
@@ -1,25 +1,23 @@
1
+ 'use client';
1
2
  import { useState, useEffect } from 'react';
2
3
 
3
- import styles from '@/styles/app.module.css';
4
- import { HelloNearContract } from '../../config';
4
+ import styles from '@/app/app.module.css';
5
5
  import { Cards } from '@/components/cards';
6
- import { useWalletSelector } from '@near-wallet-selector/react-hook';
7
6
 
8
- // Contract that the app will interact with
9
- const CONTRACT = HelloNearContract;
7
+ import { HelloNearContract } from '@/config';
8
+ import { useNearWallet } from 'near-connect-hooks';
9
+
10
10
 
11
11
  export default function HelloNear() {
12
- const { signedAccountId, viewFunction, callFunction } = useWalletSelector();
12
+ const { signedAccountId, viewFunction, callFunction } = useNearWallet();
13
13
 
14
- const [greeting, setGreeting] = useState('loading...');
14
+ const [greeting, setGreeting] = useState<string>('loading...');
15
15
  const [newGreeting, setNewGreeting] = useState('loading...');
16
16
  const [loggedIn, setLoggedIn] = useState(false);
17
17
  const [showSpinner, setShowSpinner] = useState(false);
18
18
 
19
- useEffect(() => {
20
- viewFunction({ contractId: CONTRACT, method: 'get_greeting' }).then(
21
- greeting => setGreeting(greeting)
22
- );
19
+ useEffect(() => {
20
+ viewFunction({ contractId: HelloNearContract, method: 'get_greeting' }).then((greeting) => setGreeting(greeting as string));
23
21
  }, []);
24
22
 
25
23
  useEffect(() => {
@@ -27,11 +25,17 @@ export default function HelloNear() {
27
25
  }, [signedAccountId]);
28
26
 
29
27
  const saveGreeting = async () => {
28
+ // Try to store greeting, revert if it fails
29
+ callFunction({ contractId: HelloNearContract, method: 'set_greeting', args: { greeting: newGreeting } })
30
+ .then(async () => {
31
+ const greeting = (await viewFunction({ contractId: HelloNearContract, method: 'get_greeting' })) as string;
32
+ setGreeting(greeting);
33
+ setShowSpinner(false);
34
+ });
35
+
36
+ // Assume the transaction will be successful and update the UI optimistically
30
37
  setShowSpinner(true);
31
- await callFunction({ contractId: CONTRACT, method: 'set_greeting', args: { greeting: newGreeting } });
32
- const greeting = await viewFunction({ contractId: CONTRACT, method: 'get_greeting' });
33
- setGreeting(greeting);
34
- setShowSpinner(false);
38
+ setGreeting(newGreeting);
35
39
  };
36
40
 
37
41
  return (
@@ -39,7 +43,7 @@ export default function HelloNear() {
39
43
  <div className={styles.description}>
40
44
  <p>
41
45
  Interacting with the contract: &nbsp;
42
- <code className={styles.code}>{CONTRACT}</code>
46
+ <code className={styles.code}>{HelloNearContract}</code>
43
47
  </p>
44
48
  </div>
45
49
 
@@ -52,15 +56,12 @@ export default function HelloNear() {
52
56
  type="text"
53
57
  className="form-control w-20"
54
58
  placeholder="Store a new greeting"
55
- onChange={t => setNewGreeting(t.target.value)}
59
+ onChange={(t) => setNewGreeting(t.target.value)}
56
60
  />
57
61
  <div className="input-group-append">
58
62
  <button className="btn btn-secondary" onClick={saveGreeting}>
59
63
  <span hidden={showSpinner}> Save </span>
60
- <i
61
- className="spinner-border spinner-border-sm"
62
- hidden={!showSpinner}
63
- ></i>
64
+ <i className="spinner-border spinner-border-sm" hidden={!showSpinner}></i>
64
65
  </button>
65
66
  </div>
66
67
  </div>
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+ import '@/app/globals.css';
3
+
4
+ import { Navigation } from '@/components/navigation';
5
+ import { NearProvider } from 'near-connect-hooks';
6
+
7
+ import { ReactNode } from 'react';
8
+
9
+ // Layout Component
10
+ interface RootLayoutProps {
11
+ children: ReactNode;
12
+ }
13
+
14
+ export default function RootLayout({ children }: RootLayoutProps) {
15
+ return (
16
+ <html lang="en">
17
+ <body>
18
+ <NearProvider>
19
+ <Navigation />
20
+ {children}
21
+ </NearProvider>
22
+ </body>
23
+ </html>
24
+ );
25
+ }
@@ -1,6 +1,5 @@
1
- import Link from 'next/link';
2
-
3
- import styles from '@/app/app.module.css';
1
+ import Link from "next/link";
2
+ import styles from "@/app/app.module.css";
4
3
 
5
4
  export const Cards = () => {
6
5
  return (
@@ -8,7 +7,7 @@ export const Cards = () => {
8
7
  <Link
9
8
  href="https://docs.near.org/build/web3-apps/quickstart"
10
9
  className={styles.card}
11
- target='_blank'
10
+ target="_blank"
12
11
  rel="noopener noreferrer"
13
12
  >
14
13
  <h2>
@@ -17,11 +16,7 @@ export const Cards = () => {
17
16
  <p>Learn how this application works, and what you can build on Near.</p>
18
17
  </Link>
19
18
 
20
- <Link
21
- href="/hello-near"
22
- className={styles.card}
23
- rel="noopener noreferrer"
24
- >
19
+ <Link href="/hello-near" className={styles.card} rel="noopener noreferrer">
25
20
  <h2>
26
21
  Near Integration <span>-&gt;</span>
27
22
  </h2>
@@ -0,0 +1,45 @@
1
+ import Image from 'next/image';
2
+ import Link from 'next/link';
3
+ import { useNearWallet } from 'near-connect-hooks';
4
+
5
+ import NearLogo from '../../public/near-logo.svg';
6
+
7
+ export const Navigation = () => {
8
+ const { signedAccountId, loading, signIn, signOut } = useNearWallet();
9
+
10
+ const handleAction = () => {
11
+ if (signedAccountId) {
12
+ signOut();
13
+ } else {
14
+ signIn();
15
+ }
16
+ };
17
+
18
+ const label = loading
19
+ ? "Loading..."
20
+ : signedAccountId
21
+ ? `Logout ${signedAccountId}`
22
+ : "Login";
23
+
24
+ return (
25
+ <nav className="navbar navbar-expand-lg">
26
+ <div className="container-fluid">
27
+ <Link href="/">
28
+ <Image
29
+ priority
30
+ src={NearLogo}
31
+ alt="NEAR"
32
+ width={30}
33
+ height={24}
34
+ className="d-inline-block align-text-top"
35
+ />
36
+ </Link>
37
+ <div className="navbar-nav pt-1">
38
+ <button className="btn btn-secondary" onClick={handleAction}>
39
+ {label}
40
+ </button>
41
+ </div>
42
+ </div>
43
+ </nav>
44
+ );
45
+ };
@@ -0,0 +1,42 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
9
+ "allowJs": false,
10
+ "skipLibCheck": true,
11
+ "strict": true,
12
+ "noEmit": true,
13
+ "esModuleInterop": true,
14
+ "module": "esnext",
15
+ "moduleResolution": "bundler",
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true,
18
+ "jsx": "preserve",
19
+ "baseUrl": ".",
20
+ "paths": {
21
+ "@/*": [
22
+ "src/*"
23
+ ]
24
+ },
25
+ "incremental": true,
26
+ "plugins": [
27
+ {
28
+ "name": "next"
29
+ }
30
+ ]
31
+ },
32
+ "include": [
33
+ "next-env.d.ts",
34
+ "src/**/*.ts",
35
+ "src/**/*.tsx",
36
+ "src/app/global.d.ts",
37
+ ".next/types/**/*.ts"
38
+ ],
39
+ "exclude": [
40
+ "node_modules"
41
+ ]
42
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
@@ -12,35 +12,21 @@
12
12
  "lint": "next lint"
13
13
  },
14
14
  "dependencies": {
15
- "@near-wallet-selector/bitte-wallet": "^9.0.2",
16
- "@near-wallet-selector/core": "^9.0.2",
17
- "@near-wallet-selector/ethereum-wallets": "^9.0.2",
18
- "@near-wallet-selector/here-wallet": "^9.0.2",
19
- "@near-wallet-selector/hot-wallet": "^9.0.2",
20
- "@near-wallet-selector/ledger": "^9.0.2",
21
- "@near-wallet-selector/meteor-wallet": "^9.0.2",
22
- "@near-wallet-selector/meteor-wallet-app": "^9.0.2",
23
- "@near-wallet-selector/modal-ui": "^9.0.2",
24
- "@near-wallet-selector/my-near-wallet": "^9.0.2",
25
- "@near-wallet-selector/near-mobile-wallet": "^9.0.2",
26
- "@near-wallet-selector/react-hook": "^9.0.2",
27
- "@near-wallet-selector/sender": "^9.0.2",
28
- "@near-wallet-selector/welldone-wallet": "^9.0.2",
29
- "@reown/appkit": "^1.7.7",
30
- "@reown/appkit-adapter-wagmi": "^1.7.7",
31
- "@wagmi/core": "^2.17.2",
32
15
  "bootstrap": "^5",
33
16
  "bootstrap-icons": "^1.11.3",
34
- "near-api-js": "^5.0.0",
17
+ "near-connect-hooks": "^1.0.2",
35
18
  "next": "^15",
36
19
  "react": "^18",
37
- "react-dom": "^18",
38
- "viem": "^2.30.5"
20
+ "react-dom": "^18"
39
21
  },
40
22
  "devDependencies": {
23
+ "@types/node": "24.8.1",
24
+ "@types/react": "^18.3.26",
25
+ "@types/react-dom": "^18.3.7",
41
26
  "encoding": "^0.1.13",
42
27
  "eslint": "^9",
43
28
  "eslint-config-next": "^15",
44
- "pino-pretty": "^11.2.2"
29
+ "pino-pretty": "^11.2.2",
30
+ "typescript": "^5.9.3"
45
31
  }
46
- }
32
+ }
@@ -20,7 +20,6 @@ export const Cards = () => {
20
20
  <Link
21
21
  href="/hello-near"
22
22
  className={styles.card}
23
- rel="noopener noreferrer"
24
23
  >
25
24
  <h2>
26
25
  Near Integration <span>-&gt;</span>
@@ -0,0 +1,45 @@
1
+ import Image from 'next/image';
2
+ import Link from 'next/link';
3
+ import { useNearWallet } from 'near-connect-hooks';
4
+
5
+ import NearLogo from '../../public/near-logo.svg';
6
+
7
+ export const Navigation = () => {
8
+ const { signedAccountId, loading, signIn, signOut } = useNearWallet();
9
+
10
+ const handleAction = () => {
11
+ if (signedAccountId) {
12
+ signOut();
13
+ } else {
14
+ signIn();
15
+ }
16
+ };
17
+
18
+ const label = loading
19
+ ? "Loading..."
20
+ : signedAccountId
21
+ ? `Logout ${signedAccountId}`
22
+ : "Login";
23
+
24
+ return (
25
+ <nav className="navbar navbar-expand-lg">
26
+ <div className="container-fluid">
27
+ <Link href="/">
28
+ <Image
29
+ priority
30
+ src={NearLogo}
31
+ alt="NEAR"
32
+ width={30}
33
+ height={24}
34
+ className="d-inline-block align-text-top"
35
+ />
36
+ </Link>
37
+ <div className="navbar-nav pt-1">
38
+ <button className="btn btn-secondary" onClick={handleAction}>
39
+ {label}
40
+ </button>
41
+ </div>
42
+ </div>
43
+ </nav>
44
+ );
45
+ };
@@ -0,0 +1,15 @@
1
+ import "@/styles/globals.css";
2
+
3
+ import type { AppProps } from "next/app";
4
+ import { Navigation } from "@/components/navigation";
5
+ import { NearProvider } from 'near-connect-hooks';
6
+
7
+
8
+ export default function App({ Component, pageProps }: AppProps) {
9
+ return (
10
+ <NearProvider>
11
+ <Navigation />
12
+ <Component {...pageProps} />
13
+ </NearProvider>
14
+ );
15
+ }
@@ -1,40 +1,41 @@
1
- import { useEffect, useState } from 'react';
2
1
 
3
2
  import { Cards } from '@/components/cards';
3
+
4
+ import { useEffect, useState } from 'react';
4
5
  import styles from '@/styles/app.module.css';
5
6
 
6
- import { HelloNearContract } from '@/config';
7
- import { useWalletSelector } from '@near-wallet-selector/react-hook';
7
+ import { HelloNearContract } from '../../config';
8
8
 
9
- // Contract that the app will interact with
10
- const CONTRACT = HelloNearContract;
9
+ import { useNearWallet } from 'near-connect-hooks';
11
10
 
12
11
  export default function HelloNear() {
13
- const { signedAccountId, viewFunction, callFunction } = useWalletSelector();
12
+ const { signedAccountId, viewFunction, callFunction } = useNearWallet();
14
13
 
15
- const [greeting, setGreeting] = useState('loading...');
16
- const [newGreeting, setNewGreeting] = useState('loading...');
14
+ const [greeting, setGreeting] = useState<string>('loading...');
15
+ const [newGreeting, setNewGreeting] = useState('');
17
16
  const [loggedIn, setLoggedIn] = useState(false);
18
17
  const [showSpinner, setShowSpinner] = useState(false);
19
18
 
20
19
  useEffect(() => {
21
- viewFunction({ contractId: CONTRACT, method: 'get_greeting' }).then((greeting) => setGreeting(greeting));
22
- }, [viewFunction]);
20
+ viewFunction({ contractId: HelloNearContract, method: 'get_greeting' }).then((greeting) => setGreeting(greeting as string));
21
+ }, []);
23
22
 
24
23
  useEffect(() => {
25
24
  setLoggedIn(!!signedAccountId);
26
25
  }, [signedAccountId]);
27
26
 
28
27
  const saveGreeting = async () => {
29
- callFunction({ contractId: CONTRACT, method: 'set_greeting', args: { greeting: newGreeting } })
30
- .catch(async () => {
31
- viewFunction({ contractId: CONTRACT, method: 'get_greeting' }).then((greeting) => setGreeting(greeting));
28
+ // Try to store greeting, revert if it fails
29
+ callFunction({ contractId: HelloNearContract, method: 'set_greeting', args: { greeting: newGreeting } })
30
+ .then(async () => {
31
+ const greeting = (await viewFunction({ contractId: HelloNearContract, method: 'get_greeting' })) as string;
32
+ setGreeting(greeting);
33
+ setShowSpinner(false);
32
34
  });
33
35
 
36
+ // Assume the transaction will be successful and update the UI optimistically
34
37
  setShowSpinner(true);
35
- await new Promise(resolve => setTimeout(resolve, 300));
36
38
  setGreeting(newGreeting);
37
- setShowSpinner(false);
38
39
  };
39
40
 
40
41
  return (
@@ -42,9 +43,10 @@ export default function HelloNear() {
42
43
  <div className={styles.description}>
43
44
  <p>
44
45
  Interacting with the contract: &nbsp;
45
- <code className={styles.code}>{CONTRACT}</code>
46
+ <code className={styles.code}>{HelloNearContract}</code>
46
47
  </p>
47
48
  </div>
49
+
48
50
  <div className={styles.center}>
49
51
  <h1 className="w-100">
50
52
  The contract says: <code>{greeting}</code>
@@ -1,14 +1,14 @@
1
- import Image from 'next/image';
1
+ import Image from "next/image";
2
2
 
3
- import NearLogo from '/public/near.svg';
4
- import NextLogo from '/public/next.svg';
5
- import styles from '@/styles/app.module.css';
6
- import { Cards } from '@/components/cards';
3
+ import NearLogo from "/public/near.svg";
4
+ import NextLogo from "/public/next.svg";
5
+ import { Cards } from "@/components/cards";
6
+ import styles from "@/styles/app.module.css";
7
7
 
8
8
  export default function Home() {
9
9
  return (
10
10
  <main className={styles.main}>
11
- <div className={styles.description}> </div>
11
+ <div className={styles.description}></div>
12
12
 
13
13
  <div className={styles.center}>
14
14
  <Image
@@ -24,8 +24,8 @@ export default function Home() {
24
24
  className={styles.logo}
25
25
  src={NextLogo}
26
26
  alt="Next.js Logo"
27
- width={300 * .58}
28
- height={61 * .58}
27
+ width={300 * 0.58}
28
+ height={61 * 0.58}
29
29
  priority
30
30
  />
31
31
  </div>
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": [
6
+ "./src/*"
7
+ ]
8
+ },
9
+ "jsx": "preserve",
10
+ "strict": true,
11
+ "moduleResolution": "node",
12
+ "skipLibCheck": true,
13
+ "target": "ES2017",
14
+ "lib": [
15
+ "dom",
16
+ "dom.iterable",
17
+ "esnext"
18
+ ],
19
+ "allowJs": true,
20
+ "noEmit": true,
21
+ "incremental": true,
22
+ "module": "esnext",
23
+ "esModuleInterop": true,
24
+ "resolveJsonModule": true,
25
+ "isolatedModules": true
26
+ },
27
+ "include": [
28
+ "**/*.ts",
29
+ "**/*.tsx",
30
+ "global.d.ts"
31
+ ],
32
+ "exclude": [
33
+ "node_modules"
34
+ ]
35
+ }
@@ -7,10 +7,11 @@ import reactRefresh from 'eslint-plugin-react-refresh'
7
7
  export default [
8
8
  { ignores: ['dist'] },
9
9
  {
10
- files: ['**/*.{js,jsx}'],
10
+ files: ['**/*.{js,jsx,ts,tsx}'],
11
11
  languageOptions: {
12
12
  ecmaVersion: 2020,
13
13
  globals: globals.browser,
14
+ parser: tseslint.parser,
14
15
  parserOptions: {
15
16
  ecmaVersion: 'latest',
16
17
  ecmaFeatures: { jsx: true },
@@ -22,12 +23,14 @@ export default [
22
23
  react,
23
24
  'react-hooks': reactHooks,
24
25
  'react-refresh': reactRefresh,
26
+ '@typescript-eslint': tseslint.plugin,
25
27
  },
26
28
  rules: {
27
29
  ...js.configs.recommended.rules,
28
30
  ...react.configs.recommended.rules,
29
31
  ...react.configs['jsx-runtime'].rules,
30
32
  ...reactHooks.configs.recommended.rules,
33
+ ...tseslint.configs.recommended.rules,
31
34
  'react/jsx-no-target-blank': 'off',
32
35
  'react-refresh/only-export-components': [
33
36
  'warn',