diff --git a/package-lock.json b/package-lock.json index 0b21b5c..c6c60dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,14 +13,19 @@ "@types/express": "^4.17.21", "@types/node": "^20.14.2", "@types/node-fetch": "^2.6.11", + "@types/react": "^19.0.8", "@types/sha256": "^0.2.2", "@types/sync-fetch": "^0.4.3", "cors": "^2.8.5", "delphinus-curves": "github:DelphinusLab/delphinus-curves#xgao", "dotenv": "^16.4.5", "ethers": "^6.13.1", + "react": "^18.3.1", "typescript": "^5.4.5", "zkwasm-minirollup-rpc": "github:DelphinusLab/zkWasm-minirollup-rpc" + }, + "devDependencies": { + "@types/react-redux": "^7.1.34" } }, "node_modules/@adraffy/ens-normalize": { @@ -1495,6 +1500,16 @@ "@types/send": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", + "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -1540,6 +1555,26 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, + "node_modules/@types/react": { + "version": "19.0.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", + "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.34", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz", + "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/secp256k1": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-3.5.3.tgz", @@ -1907,6 +1942,11 @@ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -2158,6 +2198,15 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2224,6 +2273,11 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", @@ -2240,6 +2294,17 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2379,6 +2444,23 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", diff --git a/package.json b/package.json index 1407d01..646c000 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,14 @@ "@types/express": "^4.17.21", "@types/node": "^20.14.2", "@types/node-fetch": "^2.6.11", + "@types/react": "^19.0.8", "@types/sha256": "^0.2.2", "@types/sync-fetch": "^0.4.3", "cors": "^2.8.5", "delphinus-curves": "github:DelphinusLab/delphinus-curves#xgao", "dotenv": "^16.4.5", "ethers": "^6.13.1", + "react": "^18.3.1", "typescript": "^5.4.5", "zkwasm-minirollup-rpc": "github:DelphinusLab/zkWasm-minirollup-rpc" }, @@ -21,5 +23,8 @@ "scripts": { "build": "npx tsc", "postinstall": "npm run build" + }, + "devDependencies": { + "@types/react-redux": "^7.1.34" } } diff --git a/src/reduxconnect.ts b/src/reduxconnect.ts index ef67801..9daf147 100644 --- a/src/reduxconnect.ts +++ b/src/reduxconnect.ts @@ -1,8 +1,9 @@ -import { createSlice } from '@reduxjs/toolkit'; +import { createSlice, Draft } from '@reduxjs/toolkit'; import { getConfig, sendTransaction, queryState, queryInitialState, sendExtrinsicTransaction } from "./connect.js"; export enum ConnectState{ Init, + OnStart, Preloading, Idle, InstallPlayer, @@ -15,11 +16,10 @@ export enum ConnectState{ export interface RequestError { errorInfo: string, - payload: any, } interface UserState { - player: PlayerInfo | null, + player: PlayerInfo, state: GlobalState, } @@ -39,6 +39,9 @@ export function createStateSlice(initialState: setConnectState: (state, action) => { state.connectState = action.payload; }, + setLastTransactionError: (state, action) => { + state.lastError = action.payload; + }, }, extraReducers: (builder) => { @@ -53,20 +56,19 @@ export function createStateSlice(initialState: .addCase(getConfig.rejected, (state, action) => { state.lastError = { errorInfo: `query config rejected: ${action.payload}`, - payload: action.payload, } }) .addCase(sendTransaction.pending, (state, action) => { state.connectState = ConnectState.WaitingTxReply; }) .addCase(sendTransaction.fulfilled, (state, action) => { - const loadedState = action.payload.state; - const loadedPlayer = action.payload.player; + const loadedState = action.payload.state ?? {} as Draft; + const loadedPlayer = action.payload.player ?? {} as Draft; state.userState = { player: loadedPlayer, state: loadedState, } - if(loadedPlayer != null) { + if(action.payload.player != null) { state.connectState = ConnectState.Idle; } else { state.connectState = ConnectState.InstallPlayer; @@ -75,7 +77,6 @@ export function createStateSlice(initialState: .addCase(sendTransaction.rejected, (state, action) => { state.lastError = { errorInfo:`send transaction rejected: ${action.payload}`, - payload: action.payload, } }) .addCase(sendExtrinsicTransaction.pending, (state, action) => { @@ -87,20 +88,19 @@ export function createStateSlice(initialState: .addCase(sendExtrinsicTransaction.rejected, (state, action) => { state.lastError = { errorInfo:`send extrinsic transaction rejected: ${action.payload}`, - payload: action.payload, } }) .addCase(queryState.pending, (state, action) => { state.connectState = ConnectState.QueryState; }) .addCase(queryState.fulfilled, (state, action) => { - const loadedState = action.payload.state; - const loadedPlayer = action.payload.player; + const loadedState = action.payload.state ?? {} as Draft; + const loadedPlayer = action.payload.player ?? {} as Draft; state.userState = { player: loadedPlayer, state: loadedState, } - if(loadedPlayer != null) { + if(action.payload.player != null) { state.connectState = ConnectState.Idle; } else { state.connectState = ConnectState.InstallPlayer; @@ -109,17 +109,16 @@ export function createStateSlice(initialState: .addCase(queryState.rejected, (state, action) => { state.lastError = { errorInfo: `query state rejected: ${action.payload}`, - payload: action.payload, } state.connectState = ConnectState.ConnectionError; }) .addCase(queryInitialState.fulfilled, (state, action) => { - const loadedState = action.payload.state; + const loadedState = action.payload.state ?? {} as Draft; if(state.userState) { state.userState.state = loadedState; } else { state.userState = { - player: null, + player: {} as Draft, state: loadedState } } @@ -128,7 +127,6 @@ export function createStateSlice(initialState: state.connectState = ConnectState.ConnectionError; state.lastError = { errorInfo: `query state rejected: ${action.payload}`, - payload: action.payload, } });