react-near-ts 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["nearToken","nearGas","createMainnetClient","createTestnetClient"],"sources":["../src/store/NearStoreProvider.tsx","../src/hooks/useAccountInfo.ts","../src/hooks/useConnectedAccount.ts","../src/hooks/useContractReadFunction.ts","../src/hooks/useExecuteTransaction.ts","../src/hooks/useNearConnector.ts","../src/store/nearStore.ts","../src/_common/utils/result.ts","../src/services/nearConnector/executeTransaction/toNearConnectActions.ts","../src/services/nearConnector/executeTransaction/executeTransaction.ts","../src/services/nearConnector/nearConnector.ts","../src/providers/NearProvider.tsx","../src/providers/MainnetNearProvider.tsx","../src/providers/TestnetNearProdiver.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\nimport type { NearStore, NearState } from '../../types/store.ts';\nimport { useStore } from 'zustand/react';\n\nconst NearStoreContext = createContext<NearStore | null>(null);\n\nexport const NearStoreProvider = (props: {\n children: ReactNode;\n nearStore: NearStore;\n}) => (\n <NearStoreContext.Provider value={props.nearStore}>\n {props.children}\n </NearStoreContext.Provider>\n);\n\nexport const useNearStore = <T extends unknown>(\n selector: (s: NearState) => T,\n): T => {\n const store = useContext(NearStoreContext);\n\n if (!store)\n throw new Error('useNearStore must be used within NearStoreProvider'); // TODO throw ReactNearTsError\n\n return useStore(store, selector);\n};\n","import { useQuery, skipToken } from '@tanstack/react-query';\nimport { useNearStore } from '../store/NearStoreProvider.tsx';\nimport type { UseAccountInfo } from '../../types/hooks/useAccountInfo.ts';\n\nexport const useAccountInfo: UseAccountInfo = (args) => {\n const getContext = useNearStore((store) => store.getContext);\n const context = getContext();\n\n const { accountId, query, ...rest } = args;\n\n return useQuery({\n queryKey: ['getAccountInfo', accountId],\n queryFn: accountId\n ? (args) =>\n context.client.getAccountInfo({\n ...rest,\n accountId,\n options: { signal: args.signal },\n })\n : skipToken,\n enabled: query?.enabled ?? true,\n });\n};\n","import { useNearStore } from '../store/NearStoreProvider.tsx';\n\nexport const useConnectedAccount = () => {\n const connectedAccountId = useNearStore((store) => store.connectedAccountId);\n return {\n connectedAccountId,\n isConnectedAccount: typeof connectedAccountId === 'string',\n };\n};\n","import { useQuery, skipToken } from '@tanstack/react-query';\nimport type {\n InnerUseContractReadFunctionArgs,\n UseContractReadFunction,\n} from '../../types/hooks/useContractReadFunction.ts';\nimport { useNearStore } from '../store/NearStoreProvider.tsx';\n\nexport const useContractReadFunction: UseContractReadFunction = (\n args: InnerUseContractReadFunctionArgs,\n): ReturnType<UseContractReadFunction> => {\n const getContext = useNearStore((store) => store.getContext);\n const context = getContext();\n\n const { query, contractAccountId, functionName, ...rest } = args;\n\n return useQuery({\n queryKey: ['callContractReadFunction', contractAccountId, functionName, rest.functionArgs],\n queryFn:\n contractAccountId && functionName\n ? ({ signal }) =>\n context.client.callContractReadFunction({\n ...rest,\n contractAccountId,\n functionName,\n options: {\n ...rest.options,\n signal,\n },\n })\n : skipToken,\n enabled: query?.enabled ?? true,\n });\n};\n","import { useMutation } from '@tanstack/react-query';\nimport { useNearStore } from '../store/NearStoreProvider.tsx';\nimport type { StoreContext } from '../../types/store.ts';\nimport type {\n UseExecuteTransaction,\n ExecuteTransactionArgs,\n} from '../../types/hooks/useExecuteTransaction.ts';\n\nconst tryOnManySigners = async (args: ExecuteTransactionArgs, context: StoreContext) => {\n const signers = context.signers;\n if (signers.length === 0) throw new Error('No signers available');\n\n const executeTransaction = async (signerIndex: number) => {\n const signer = signers[signerIndex];\n\n const result = await signer.safeExecuteTransaction({ intent: args.intent });\n if (result.ok) return result.value;\n\n // TODO right now we only support one signer - we will support multiple signers after adding\n // canExecuteTransaction method to all signers\n throw result.error;\n };\n\n return executeTransaction(0);\n};\n\nexport const useExecuteTransaction: UseExecuteTransaction = () => {\n const getContext = useNearStore((s) => s.getContext);\n const context = getContext();\n\n return useMutation({\n mutationFn: (args) => tryOnManySigners(args, context),\n });\n};\n","import * as z from 'zod/mini';\nimport { NearConnector } from '@hot-labs/near-connect';\nimport { useNearStore } from '../store/NearStoreProvider.tsx';\nimport { useMutation } from '@tanstack/react-query';\nimport type { UseNearConnect } from '../../types/hooks/useNearConnect.ts';\n\nconst NearConnectorServiceSchema = z.object({\n nearConnector: z.object({\n serviceBox: z.object({\n connector: z.instanceof(NearConnector),\n }),\n }),\n});\n\nexport const useNearConnector: UseNearConnect = () => {\n const getContext = useNearStore((store) => store.getContext);\n const setSigners = useNearStore((store) => store.setSigners);\n const clearSigners = useNearStore((store) => store.clearSigners);\n const setConnectedAccountId = useNearStore((store) => store.setConnectedAccountId);\n const context = getContext();\n\n const connect = useMutation<void, Error, void, unknown>({\n mutationFn: async () => {\n const services = NearConnectorServiceSchema.parse(context.services);\n const connector = services.nearConnector.serviceBox.connector;\n\n const wallet = await connector.connect();\n const accounts = await wallet.getAccounts();\n const connectedAccountId = accounts[0].accountId;\n\n setSigners(connectedAccountId);\n setConnectedAccountId(connectedAccountId);\n },\n });\n\n const disconnect = useMutation<void, Error, void, unknown>({\n mutationFn: async () => {\n const services = NearConnectorServiceSchema.parse(context.services);\n const connector = services.nearConnector.serviceBox.connector;\n\n await connector.disconnect();\n clearSigners();\n setConnectedAccountId(undefined);\n },\n });\n\n return {\n connect,\n disconnect,\n };\n};\n","import { createStore } from 'zustand/vanilla';\nimport { persist } from 'zustand/middleware';\nimport type { AccountId } from 'near-api-ts';\nimport type { CreateNearStore, StoreContext, NearState } from '../../types/store.ts';\nimport type { ServiceId, Service } from '../../types/services/_common.ts';\n\nexport const createNearStore: CreateNearStore = (args) => {\n // TODO Validate args\n const { storeName = 'react-near-ts', networkId, clientCreator, serviceCreators } = args;\n\n // TODO check if service already exists; If so - throw an error\n const services = serviceCreators.reduce(\n (acc, creator) => {\n acc[creator.serviceId] = creator.createService();\n return acc;\n },\n {} as Record<ServiceId, Service>,\n );\n\n // Create Context\n const context: StoreContext = {\n serviceCreators,\n client: clientCreator(),\n services,\n signers: [],\n };\n const getContext = () => context;\n\n const setSigners = (connectedAccountId: AccountId) => {\n context.signers = context.serviceCreators.map((creator) =>\n creator.createSigner({\n signerAccountId: connectedAccountId,\n client: context.client,\n serviceBox: context.services[creator.serviceId].serviceBox,\n }),\n );\n };\n\n const clearSigners = () => {\n context.signers = [];\n };\n\n // Create Store\n return createStore<NearState>()(\n persist(\n (set) => ({\n networkId,\n connectedAccountId: undefined,\n getContext,\n setSigners,\n clearSigners,\n setConnectedAccountId: (connectedAccountId) => {\n set(() => ({ connectedAccountId }));\n },\n }),\n {\n name: `${storeName}:${networkId}`,\n version: 1,\n partialize: (s) => ({ connectedAccountId: s.connectedAccountId }),\n onRehydrateStorage: () => (state) => {\n if (state?.connectedAccountId) state.setSigners(state.connectedAccountId);\n },\n },\n ),\n );\n};\n","import type { ResultErr, ResultOk } from '../../../types/_common.ts';\n\nexport const result = {\n ok: <V>(value: V): ResultOk<V> => ({ ok: true, value }),\n err: <E>(error: E): ResultErr<E> => ({ ok: false, error }),\n};\n","import { nearToken, nearGas } from 'near-api-ts';\nimport type { Action as NatAction, TransactionIntent } from 'near-api-ts';\nimport type { NearConnectAction } from '../../../../types/services/nearConnect.ts';\n\nconst toNearConnectAction = (action: NatAction): NearConnectAction => {\n if (action.actionType === 'CreateAccount')\n return {\n createAccount: {},\n };\n\n if (action.actionType === 'Transfer')\n return {\n transfer: { deposit: nearToken(action.amount).yoctoNear },\n };\n\n if (action.actionType === 'AddKey')\n return {\n addKey: {\n publicKey: action.publicKey,\n accessKey: {\n nonce: 0n, // deprecated field\n permission:\n action.accessType === 'FullAccess'\n ? { fullAccess: {} }\n : {\n functionCall: {\n receiverId: action.contractAccountId,\n methodNames: action.allowedFunctions,\n allowance: action.gasBudget ? nearToken(action.gasBudget).yoctoNear : undefined,\n },\n },\n },\n },\n };\n\n if (action.actionType === 'FunctionCall')\n return {\n functionCall: {\n methodName: action.functionName,\n args: action.functionArgs,\n gas: nearGas(action.gasLimit).gas,\n deposit: action.attachedDeposit ? nearToken(action.attachedDeposit).yoctoNear : 0n,\n },\n };\n\n if (action.actionType === 'DeployContract')\n return {\n deployContract: {\n code: action.wasmBytes,\n },\n };\n\n if (action.actionType === 'Stake')\n return {\n stake: {\n stake: nearToken(action.amount).yoctoNear,\n publicKey: action.validatorPublicKey,\n },\n };\n\n if (action.actionType === 'DeleteKey')\n return {\n deleteKey: {\n publicKey: action.publicKey,\n },\n };\n\n if (action.actionType === 'DeleteAccount')\n return {\n deleteAccount: {\n beneficiaryId: action.beneficiaryAccountId,\n },\n };\n\n // Never reached\n throw new Error(`Unsupported action type: ${action}`);\n};\n\nexport const toNearConnectActions = (intent: TransactionIntent): NearConnectAction[] => {\n if (intent.action) return [toNearConnectAction(intent.action)];\n if (intent.actions) return intent.actions.map((action) => toNearConnectAction(action));\n return [];\n};\n","import { result } from '../../../_common/utils/result.ts';\nimport type { CreateSafeExecuteTransaction } from '../../../../types/services/nearConnect.ts';\nimport { toNearConnectActions } from './toNearConnectActions.ts';\n\nexport const createSafeExecuteTransaction: CreateSafeExecuteTransaction =\n (connector) => async (args) => {\n try {\n const wallet = await connector.wallet();\n\n const finalExecutionOutcome = await wallet.signAndSendTransaction({\n actions: toNearConnectActions(args.intent),\n receiverId: args.intent.receiverAccountId,\n });\n\n return result.ok({ rawRpcResult: finalExecutionOutcome });\n } catch (e) {\n return result.err(e);\n }\n };\n","import { NearConnector } from '@hot-labs/near-connect';\nimport { createSafeExecuteTransaction } from './executeTransaction/executeTransaction.ts';\nimport type { CreateNearConnectorService } from '../../../types/services/nearConnect.ts';\n\nconst serviceId = 'nearConnector';\n\nexport const createNearConnectorService: CreateNearConnectorService = (args) => ({\n serviceId,\n\n createService: () => {\n const connector = new NearConnector({ network: args.networkId });\n return {\n serviceId,\n serviceBox: { connector },\n };\n },\n\n createSigner: (args: { serviceBox: { connector: NearConnector } }) => {\n return {\n serviceId,\n safeExecuteTransaction: createSafeExecuteTransaction(args.serviceBox.connector),\n };\n },\n});\n","import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { NearStoreProvider } from '../store/NearStoreProvider.tsx';\nimport type { ReactNode } from 'react';\nimport type { NearStore } from '../../types/store.ts';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n mutations: { retry: false },\n },\n});\n\ntype NearProviderProps = {\n nearStore: NearStore;\n children: ReactNode;\n};\n\nexport const NearProvider = (props: NearProviderProps) => (\n <NearStoreProvider nearStore={props.nearStore}>\n <QueryClientProvider client={queryClient}>\n {props.children}\n </QueryClientProvider>\n </NearStoreProvider>\n);\n","import { createNearStore } from '../store/nearStore.ts';\nimport { createMainnetClient } from 'near-api-ts';\nimport { createNearConnectorService } from '../services/nearConnector/nearConnector.ts';\nimport { NearProvider } from './NearProvider.tsx';\nimport type { ReactNode } from 'react';\n\nconst createMainnetNearStore = () =>\n createNearStore({\n networkId: 'mainnet',\n clientCreator: createMainnetClient,\n serviceCreators: [createNearConnectorService({ networkId: 'mainnet' })],\n });\n\nexport const MainnetNearProvider = (props: { children: ReactNode }) => (\n <NearProvider nearStore={createMainnetNearStore()}>{props.children}</NearProvider>\n);\n","import { createNearStore } from '../store/nearStore.ts';\nimport { createTestnetClient } from 'near-api-ts';\nimport { createNearConnectorService } from '../services/nearConnector/nearConnector.ts';\nimport { NearProvider } from './NearProvider.tsx';\nimport type { ReactNode } from 'react';\n\nconst createTestnetNearStore = () =>\n createNearStore({\n networkId: 'testnet',\n clientCreator: createTestnetClient,\n serviceCreators: [createNearConnectorService({ networkId: 'testnet' })],\n });\n\nexport const TestnetNearProvider = (props: { children: ReactNode }) => (\n <NearProvider nearStore={createTestnetNearStore()}>{props.children}</NearProvider>\n);\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "react-near-ts",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript-first toolkit for integrating NEAR Protocol with your React application",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "peerDependencies": {
10
+ "@tanstack/react-query": ">=5.90.21 <6",
11
+ "react": ">=19.2.0 <20",
12
+ "react-dom": ">=19.2.0 <20",
13
+ "zod": ">=4.3.0 <5"
14
+ },
15
+ "dependencies": {
16
+ "@hot-labs/near-connect": "^0.10.0",
17
+ "zustand": "^5.0.11",
18
+ "near-api-ts": "0.8.0"
19
+ },
20
+ "devDependencies": {
21
+ "@tanstack/react-query": "^5.90.21",
22
+ "@types/node": "^24.10.1",
23
+ "@types/react": "^19.2.5",
24
+ "@types/react-dom": "^19.2.3",
25
+ "react": "^19.2.0",
26
+ "react-dom": "^19.2.0",
27
+ "tsdown": "0.20.3",
28
+ "zod": "^4.3.6"
29
+ },
30
+ "types": "./dist/index.d.mts",
31
+ "module": "./dist/index.mjs",
32
+ "main": "./dist/index.mjs",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.mts",
36
+ "import": "./dist/index.mjs",
37
+ "default": "./dist/index.mjs"
38
+ }
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "src",
43
+ "types",
44
+ "package.json",
45
+ "LICENSE.md",
46
+ "README.md"
47
+ ],
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/near/near-api-ts.git",
51
+ "directory": "packages/react-near-ts"
52
+ },
53
+ "keywords": [
54
+ "near",
55
+ "near-protocol",
56
+ "near-api",
57
+ "react",
58
+ "react-query",
59
+ "typescript",
60
+ "web3",
61
+ "blockchain"
62
+ ],
63
+ "author": {
64
+ "name": "Volodymyr <eclipseeer> Bilyk",
65
+ "email": "volodymyr@lantstool.dev"
66
+ },
67
+ "license": "MIT",
68
+ "scripts": {
69
+ "build": "tsdown",
70
+ "dev": "tsdown --watch",
71
+ "typecheck": "tsc --noEmit"
72
+ }
73
+ }
@@ -0,0 +1,6 @@
1
+ import type { ResultErr, ResultOk } from '../../../types/_common.ts';
2
+
3
+ export const result = {
4
+ ok: <V>(value: V): ResultOk<V> => ({ ok: true, value }),
5
+ err: <E>(error: E): ResultErr<E> => ({ ok: false, error }),
6
+ };
@@ -0,0 +1,23 @@
1
+ import { useQuery, skipToken } from '@tanstack/react-query';
2
+ import { useNearStore } from '../store/NearStoreProvider.tsx';
3
+ import type { UseAccountInfo } from '../../types/hooks/useAccountInfo.ts';
4
+
5
+ export const useAccountInfo: UseAccountInfo = (args) => {
6
+ const getContext = useNearStore((store) => store.getContext);
7
+ const context = getContext();
8
+
9
+ const { accountId, query, ...rest } = args;
10
+
11
+ return useQuery({
12
+ queryKey: ['getAccountInfo', accountId],
13
+ queryFn: accountId
14
+ ? (args) =>
15
+ context.client.getAccountInfo({
16
+ ...rest,
17
+ accountId,
18
+ options: { signal: args.signal },
19
+ })
20
+ : skipToken,
21
+ enabled: query?.enabled ?? true,
22
+ });
23
+ };
@@ -0,0 +1,9 @@
1
+ import { useNearStore } from '../store/NearStoreProvider.tsx';
2
+
3
+ export const useConnectedAccount = () => {
4
+ const connectedAccountId = useNearStore((store) => store.connectedAccountId);
5
+ return {
6
+ connectedAccountId,
7
+ isConnectedAccount: typeof connectedAccountId === 'string',
8
+ };
9
+ };
@@ -0,0 +1,33 @@
1
+ import { useQuery, skipToken } from '@tanstack/react-query';
2
+ import type {
3
+ InnerUseContractReadFunctionArgs,
4
+ UseContractReadFunction,
5
+ } from '../../types/hooks/useContractReadFunction.ts';
6
+ import { useNearStore } from '../store/NearStoreProvider.tsx';
7
+
8
+ export const useContractReadFunction: UseContractReadFunction = (
9
+ args: InnerUseContractReadFunctionArgs,
10
+ ): ReturnType<UseContractReadFunction> => {
11
+ const getContext = useNearStore((store) => store.getContext);
12
+ const context = getContext();
13
+
14
+ const { query, contractAccountId, functionName, ...rest } = args;
15
+
16
+ return useQuery({
17
+ queryKey: ['callContractReadFunction', contractAccountId, functionName, rest.functionArgs],
18
+ queryFn:
19
+ contractAccountId && functionName
20
+ ? ({ signal }) =>
21
+ context.client.callContractReadFunction({
22
+ ...rest,
23
+ contractAccountId,
24
+ functionName,
25
+ options: {
26
+ ...rest.options,
27
+ signal,
28
+ },
29
+ })
30
+ : skipToken,
31
+ enabled: query?.enabled ?? true,
32
+ });
33
+ };
@@ -0,0 +1,34 @@
1
+ import { useMutation } from '@tanstack/react-query';
2
+ import { useNearStore } from '../store/NearStoreProvider.tsx';
3
+ import type { StoreContext } from '../../types/store.ts';
4
+ import type {
5
+ UseExecuteTransaction,
6
+ ExecuteTransactionArgs,
7
+ } from '../../types/hooks/useExecuteTransaction.ts';
8
+
9
+ const tryOnManySigners = async (args: ExecuteTransactionArgs, context: StoreContext) => {
10
+ const signers = context.signers;
11
+ if (signers.length === 0) throw new Error('No signers available');
12
+
13
+ const executeTransaction = async (signerIndex: number) => {
14
+ const signer = signers[signerIndex];
15
+
16
+ const result = await signer.safeExecuteTransaction({ intent: args.intent });
17
+ if (result.ok) return result.value;
18
+
19
+ // TODO right now we only support one signer - we will support multiple signers after adding
20
+ // canExecuteTransaction method to all signers
21
+ throw result.error;
22
+ };
23
+
24
+ return executeTransaction(0);
25
+ };
26
+
27
+ export const useExecuteTransaction: UseExecuteTransaction = () => {
28
+ const getContext = useNearStore((s) => s.getContext);
29
+ const context = getContext();
30
+
31
+ return useMutation({
32
+ mutationFn: (args) => tryOnManySigners(args, context),
33
+ });
34
+ };
@@ -0,0 +1,51 @@
1
+ import * as z from 'zod/mini';
2
+ import { NearConnector } from '@hot-labs/near-connect';
3
+ import { useNearStore } from '../store/NearStoreProvider.tsx';
4
+ import { useMutation } from '@tanstack/react-query';
5
+ import type { UseNearConnect } from '../../types/hooks/useNearConnect.ts';
6
+
7
+ const NearConnectorServiceSchema = z.object({
8
+ nearConnector: z.object({
9
+ serviceBox: z.object({
10
+ connector: z.instanceof(NearConnector),
11
+ }),
12
+ }),
13
+ });
14
+
15
+ export const useNearConnector: UseNearConnect = () => {
16
+ const getContext = useNearStore((store) => store.getContext);
17
+ const setSigners = useNearStore((store) => store.setSigners);
18
+ const clearSigners = useNearStore((store) => store.clearSigners);
19
+ const setConnectedAccountId = useNearStore((store) => store.setConnectedAccountId);
20
+ const context = getContext();
21
+
22
+ const connect = useMutation<void, Error, void, unknown>({
23
+ mutationFn: async () => {
24
+ const services = NearConnectorServiceSchema.parse(context.services);
25
+ const connector = services.nearConnector.serviceBox.connector;
26
+
27
+ const wallet = await connector.connect();
28
+ const accounts = await wallet.getAccounts();
29
+ const connectedAccountId = accounts[0].accountId;
30
+
31
+ setSigners(connectedAccountId);
32
+ setConnectedAccountId(connectedAccountId);
33
+ },
34
+ });
35
+
36
+ const disconnect = useMutation<void, Error, void, unknown>({
37
+ mutationFn: async () => {
38
+ const services = NearConnectorServiceSchema.parse(context.services);
39
+ const connector = services.nearConnector.serviceBox.connector;
40
+
41
+ await connector.disconnect();
42
+ clearSigners();
43
+ setConnectedAccountId(undefined);
44
+ },
45
+ });
46
+
47
+ return {
48
+ connect,
49
+ disconnect,
50
+ };
51
+ };
package/src/index.ts ADDED
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+
3
+ // Lib
4
+ export { useAccountInfo } from './hooks/useAccountInfo.ts';
5
+ export { useConnectedAccount } from './hooks/useConnectedAccount.ts';
6
+ export { useContractReadFunction } from './hooks/useContractReadFunction.ts';
7
+ export { useExecuteTransaction } from './hooks/useExecuteTransaction.ts';
8
+ export { useNearConnector } from './hooks/useNearConnector.ts';
9
+ export { MainnetNearProvider } from './providers/MainnetNearProvider.tsx';
10
+ export { NearProvider } from './providers/NearProvider.tsx';
11
+ export { TestnetNearProvider } from './providers/TestnetNearProdiver.tsx';
12
+ export { createNearStore } from './store/nearStore.ts';
13
+ export { createNearConnectorService } from './services/nearConnector/nearConnector.ts';
14
+
15
+ // near-api-ts reexports
16
+ export {
17
+ createTestnetClient,
18
+ createMainnetClient,
19
+ createClient,
20
+ // actionCreators
21
+ createAccount,
22
+ transfer,
23
+ addFullAccessKey,
24
+ addFunctionCallKey,
25
+ functionCall,
26
+ deployContract,
27
+ stake,
28
+ deleteKey,
29
+ deleteAccount,
30
+ //utils
31
+ keyPair,
32
+ randomEd25519KeyPair,
33
+ randomSecp256k1KeyPair,
34
+ nearToken,
35
+ near,
36
+ yoctoNear,
37
+ nearGas,
38
+ gas,
39
+ teraGas,
40
+ fromJsonBytes,
41
+ toJsonBytes,
42
+ } from 'near-api-ts';
43
+
44
+ export type { DeserializeResultFnArgs } from 'near-api-ts';
@@ -0,0 +1,16 @@
1
+ import { createNearStore } from '../store/nearStore.ts';
2
+ import { createMainnetClient } from 'near-api-ts';
3
+ import { createNearConnectorService } from '../services/nearConnector/nearConnector.ts';
4
+ import { NearProvider } from './NearProvider.tsx';
5
+ import type { ReactNode } from 'react';
6
+
7
+ const createMainnetNearStore = () =>
8
+ createNearStore({
9
+ networkId: 'mainnet',
10
+ clientCreator: createMainnetClient,
11
+ serviceCreator: createNearConnectorService({ networkId: 'mainnet' }),
12
+ });
13
+
14
+ export const MainnetNearProvider = (props: { children: ReactNode }) => (
15
+ <NearProvider nearStore={createMainnetNearStore()}>{props.children}</NearProvider>
16
+ );
@@ -0,0 +1,24 @@
1
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
+ import { NearStoreProvider } from '../store/NearStoreProvider.tsx';
3
+ import type { ReactNode } from 'react';
4
+ import type { NearStore } from '../../types/store.ts';
5
+
6
+ const queryClient = new QueryClient({
7
+ defaultOptions: {
8
+ queries: { retry: false },
9
+ mutations: { retry: false },
10
+ },
11
+ });
12
+
13
+ type NearProviderProps = {
14
+ nearStore: NearStore;
15
+ children: ReactNode;
16
+ };
17
+
18
+ export const NearProvider = (props: NearProviderProps) => (
19
+ <NearStoreProvider nearStore={props.nearStore}>
20
+ <QueryClientProvider client={queryClient}>
21
+ {props.children}
22
+ </QueryClientProvider>
23
+ </NearStoreProvider>
24
+ );
@@ -0,0 +1,16 @@
1
+ import { createNearStore } from '../store/nearStore.ts';
2
+ import { createTestnetClient } from 'near-api-ts';
3
+ import { createNearConnectorService } from '../services/nearConnector/nearConnector.ts';
4
+ import { NearProvider } from './NearProvider.tsx';
5
+ import type { ReactNode } from 'react';
6
+
7
+ const createTestnetNearStore = () =>
8
+ createNearStore({
9
+ networkId: 'testnet',
10
+ clientCreator: createTestnetClient,
11
+ serviceCreator: createNearConnectorService({ networkId: 'testnet' }),
12
+ });
13
+
14
+ export const TestnetNearProvider = (props: { children: ReactNode }) => (
15
+ <NearProvider nearStore={createTestnetNearStore()}>{props.children}</NearProvider>
16
+ );
@@ -0,0 +1,22 @@
1
+ // import { createMemoryKeyService, createMemorySigner } from 'near-api-ts';
2
+ //
3
+ // export const createMemoryServiceFactory = ({
4
+ // keySources,
5
+ // // signer: { taskQueue },
6
+ // }: any) => {
7
+ // return {
8
+ // serviceId: 'memory',
9
+ // createService: () => {
10
+ // const keyService = createMemoryKeyService({ keySources });
11
+ // return { keyService };
12
+ // },
13
+ // // args should be general and one for all services;
14
+ // createSigner: ({ signerAccountId, client, service }: any) =>
15
+ // createMemorySigner({
16
+ // signerAccountId,
17
+ // client,
18
+ // keyService: service.keyService,
19
+ // }),
20
+ // };
21
+ // };
22
+
@@ -0,0 +1,19 @@
1
+ import { result } from '../../../_common/utils/result.ts';
2
+ import type { CreateSafeExecuteTransaction } from '../../../../types/services/nearConnect.ts';
3
+ import { toNearConnectActions } from './toNearConnectActions.ts';
4
+
5
+ export const createSafeExecuteTransaction: CreateSafeExecuteTransaction =
6
+ (connector) => async (args) => {
7
+ try {
8
+ const wallet = await connector.wallet();
9
+
10
+ const finalExecutionOutcome = await wallet.signAndSendTransaction({
11
+ actions: toNearConnectActions(args.intent),
12
+ receiverId: args.intent.receiverAccountId,
13
+ });
14
+
15
+ return result.ok({ rawRpcResult: finalExecutionOutcome });
16
+ } catch (e) {
17
+ return result.err(e);
18
+ }
19
+ };
@@ -0,0 +1,83 @@
1
+ import { nearToken, nearGas } from 'near-api-ts';
2
+ import type { Action as NatAction, TransactionIntent } from 'near-api-ts';
3
+ import type { NearConnectAction } from '../../../../types/services/nearConnect.ts';
4
+
5
+ const toNearConnectAction = (action: NatAction): NearConnectAction => {
6
+ if (action.actionType === 'CreateAccount')
7
+ return {
8
+ createAccount: {},
9
+ };
10
+
11
+ if (action.actionType === 'Transfer')
12
+ return {
13
+ transfer: { deposit: nearToken(action.amount).yoctoNear },
14
+ };
15
+
16
+ if (action.actionType === 'AddKey')
17
+ return {
18
+ addKey: {
19
+ publicKey: action.publicKey,
20
+ accessKey: {
21
+ nonce: 0n, // deprecated field
22
+ permission:
23
+ action.accessType === 'FullAccess'
24
+ ? { fullAccess: {} }
25
+ : {
26
+ functionCall: {
27
+ receiverId: action.contractAccountId,
28
+ methodNames: action.allowedFunctions,
29
+ allowance: action.gasBudget ? nearToken(action.gasBudget).yoctoNear : undefined,
30
+ },
31
+ },
32
+ },
33
+ },
34
+ };
35
+
36
+ if (action.actionType === 'FunctionCall')
37
+ return {
38
+ functionCall: {
39
+ methodName: action.functionName,
40
+ args: action.functionArgs,
41
+ gas: nearGas(action.gasLimit).gas,
42
+ deposit: action.attachedDeposit ? nearToken(action.attachedDeposit).yoctoNear : 0n,
43
+ },
44
+ };
45
+
46
+ if (action.actionType === 'DeployContract')
47
+ return {
48
+ deployContract: {
49
+ code: action.wasmBytes,
50
+ },
51
+ };
52
+
53
+ if (action.actionType === 'Stake')
54
+ return {
55
+ stake: {
56
+ stake: nearToken(action.amount).yoctoNear,
57
+ publicKey: action.validatorPublicKey,
58
+ },
59
+ };
60
+
61
+ if (action.actionType === 'DeleteKey')
62
+ return {
63
+ deleteKey: {
64
+ publicKey: action.publicKey,
65
+ },
66
+ };
67
+
68
+ if (action.actionType === 'DeleteAccount')
69
+ return {
70
+ deleteAccount: {
71
+ beneficiaryId: action.beneficiaryAccountId,
72
+ },
73
+ };
74
+
75
+ // Never reached
76
+ throw new Error(`Unsupported action type: ${action}`);
77
+ };
78
+
79
+ export const toNearConnectActions = (intent: TransactionIntent): NearConnectAction[] => {
80
+ if (intent.action) return [toNearConnectAction(intent.action)];
81
+ if (intent.actions) return intent.actions.map((action) => toNearConnectAction(action));
82
+ return [];
83
+ };
@@ -0,0 +1,24 @@
1
+ import { NearConnector } from '@hot-labs/near-connect';
2
+ import { createSafeExecuteTransaction } from './executeTransaction/executeTransaction.ts';
3
+ import type { CreateNearConnectorService } from '../../../types/services/nearConnect.ts';
4
+
5
+ const serviceId = 'nearConnector';
6
+
7
+ export const createNearConnectorService: CreateNearConnectorService = (args) => ({
8
+ serviceId,
9
+
10
+ createService: () => {
11
+ const connector = new NearConnector({ network: args.networkId });
12
+ return {
13
+ serviceId,
14
+ serviceBox: { connector },
15
+ };
16
+ },
17
+
18
+ createSigner: (args: { serviceBox: { connector: NearConnector } }) => {
19
+ return {
20
+ serviceId,
21
+ safeExecuteTransaction: createSafeExecuteTransaction(args.serviceBox.connector),
22
+ };
23
+ },
24
+ });
@@ -0,0 +1,25 @@
1
+ import { createContext, useContext, type ReactNode } from 'react';
2
+ import type { NearStore, NearState } from '../../types/store.ts';
3
+ import { useStore } from 'zustand/react';
4
+
5
+ const NearStoreContext = createContext<NearStore | null>(null);
6
+
7
+ export const NearStoreProvider = (props: {
8
+ children: ReactNode;
9
+ nearStore: NearStore;
10
+ }) => (
11
+ <NearStoreContext.Provider value={props.nearStore}>
12
+ {props.children}
13
+ </NearStoreContext.Provider>
14
+ );
15
+
16
+ export const useNearStore = <T extends unknown>(
17
+ selector: (s: NearState) => T,
18
+ ): T => {
19
+ const store = useContext(NearStoreContext);
20
+
21
+ if (!store)
22
+ throw new Error('useNearStore must be used within NearStoreProvider'); // TODO throw ReactNearTsError
23
+
24
+ return useStore(store, selector);
25
+ };
@@ -0,0 +1,68 @@
1
+ import { createStore } from 'zustand/vanilla';
2
+ import { persist } from 'zustand/middleware';
3
+ import type { AccountId } from 'near-api-ts';
4
+ import type { CreateNearStore, StoreContext, NearState } from '../../types/store.ts';
5
+ import type { ServiceId, Service } from '../../types/services/_common.ts';
6
+
7
+ export const createNearStore: CreateNearStore = (args) => {
8
+ // TODO Validate args
9
+ const { storeName = 'react-near-ts', networkId, clientCreator, serviceCreator } = args;
10
+ // Temporary until we will support multiple services
11
+ const serviceCreators = [serviceCreator];
12
+
13
+ // TODO check if service already exists; If so - throw an error
14
+ const services = serviceCreators.reduce(
15
+ (acc, creator) => {
16
+ acc[creator.serviceId] = creator.createService();
17
+ return acc;
18
+ },
19
+ {} as Record<ServiceId, Service>,
20
+ );
21
+
22
+ // Create Context
23
+ const context: StoreContext = {
24
+ serviceCreators,
25
+ client: clientCreator(),
26
+ services,
27
+ signers: [],
28
+ };
29
+ const getContext = () => context;
30
+
31
+ const setSigners = (connectedAccountId: AccountId) => {
32
+ context.signers = context.serviceCreators.map((creator) =>
33
+ creator.createSigner({
34
+ signerAccountId: connectedAccountId,
35
+ client: context.client,
36
+ serviceBox: context.services[creator.serviceId].serviceBox,
37
+ }),
38
+ );
39
+ };
40
+
41
+ const clearSigners = () => {
42
+ context.signers = [];
43
+ };
44
+
45
+ // Create Store
46
+ return createStore<NearState>()(
47
+ persist(
48
+ (set) => ({
49
+ networkId,
50
+ connectedAccountId: undefined,
51
+ getContext,
52
+ setSigners,
53
+ clearSigners,
54
+ setConnectedAccountId: (connectedAccountId) => {
55
+ set(() => ({ connectedAccountId }));
56
+ },
57
+ }),
58
+ {
59
+ name: `${storeName}:${networkId}`,
60
+ version: 1,
61
+ partialize: (s) => ({ connectedAccountId: s.connectedAccountId }),
62
+ onRehydrateStorage: () => (state) => {
63
+ if (state?.connectedAccountId) state.setSigners(state.connectedAccountId);
64
+ },
65
+ },
66
+ ),
67
+ );
68
+ };
@@ -0,0 +1,7 @@
1
+ export type KeyIf<K extends PropertyKey, V> = [V] extends [undefined]
2
+ ? { [P in K]?: never }
3
+ : { [P in K]: V };
4
+
5
+ export type ResultOk<V> = { ok: true; value: V };
6
+ export type ResultErr<E> = { ok: false; error: E };
7
+ export type Result<V, E> = ResultOk<V> | ResultErr<E>;