@matchain/matchid-sdk-react 0.1.11 → 0.1.12
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.d.mts +107 -24
- package/dist/index.d.ts +107 -24
- package/dist/index.js +127 -55
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +126 -55
- package/dist/index.mjs.map +1 -1
- package/example/package.json +1 -0
- package/example/src/App.tsx +7 -3
- package/example/src/components/Login/index.tsx +73 -0
- package/example/src/components/RoutePrivate/index.tsx +9 -0
- package/example/src/pages/{Login.tsx → User.tsx} +7 -86
- package/example/src/pages/Wallet.tsx +130 -0
- package/example/tsconfig.json +5 -1
- package/example/vite.config.ts +1 -0
- package/package.json +1 -1
package/example/package.json
CHANGED
package/example/src/App.tsx
CHANGED
|
@@ -3,8 +3,10 @@ import {MatchProvider} from "@matchain/matchid-sdk-react";
|
|
|
3
3
|
import {BrowserRouter as Router, Routes, Route, Link} from 'react-router-dom';
|
|
4
4
|
import Home from "./pages/Home";
|
|
5
5
|
import './app.css'
|
|
6
|
-
import
|
|
6
|
+
import User from "./pages/User";
|
|
7
7
|
import "@matchain/matchid-sdk-react/index.css"
|
|
8
|
+
import RoutePrivate from "./components/RoutePrivate";
|
|
9
|
+
import Wallet from "@/pages/Wallet";
|
|
8
10
|
|
|
9
11
|
const getState = () => {
|
|
10
12
|
if (window.localStorage.getItem('match-local')) {
|
|
@@ -46,12 +48,14 @@ function App() {
|
|
|
46
48
|
</div>
|
|
47
49
|
<nav className={`text-2xl mb-5 p-2 text-red-600 flex gap-10`}>
|
|
48
50
|
<Link to="/">Home</Link>
|
|
49
|
-
<Link to="/
|
|
51
|
+
<Link to="/user">User</Link>
|
|
52
|
+
<Link to="/wallet">Wallet</Link>
|
|
50
53
|
</nav>
|
|
51
54
|
<div className={`p-4`}>
|
|
52
55
|
<Routes>
|
|
53
56
|
<Route path="/" element={<Home/>}/>
|
|
54
|
-
<Route path="/
|
|
57
|
+
<Route path="/user" element={<User/>}/>
|
|
58
|
+
<Route path="/wallet" element={<Wallet/>}/>
|
|
55
59
|
</Routes>
|
|
56
60
|
</div>
|
|
57
61
|
</Router>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {Hooks,Components} from "@matchain/matchid-sdk-react/index";
|
|
3
|
+
const { useUserInfo} = Hooks
|
|
4
|
+
const {EmailModal,LoginModal,LoginBox,LoginPanel} = Components
|
|
5
|
+
export default function Login(){
|
|
6
|
+
const {
|
|
7
|
+
loginByWallet,
|
|
8
|
+
loginByTwitter,
|
|
9
|
+
loginByGoogle,
|
|
10
|
+
loginByEmail,
|
|
11
|
+
getLoginEmailCode,
|
|
12
|
+
loginByTelegram,
|
|
13
|
+
} = useUserInfo();
|
|
14
|
+
const [email, setEmail] = React.useState('')
|
|
15
|
+
const [code, setCode] = React.useState('')
|
|
16
|
+
const [emailOpen, setEmailOpen] = React.useState(false)
|
|
17
|
+
const [loginOpen, setLoginOpen] = React.useState(false)
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className={`flex flex-col gap-10`}>
|
|
21
|
+
<div className={`flex gap-5`}>
|
|
22
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
23
|
+
onClick={loginByWallet}>Wallet
|
|
24
|
+
</button>
|
|
25
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
26
|
+
onClick={loginByTwitter}>Twitter
|
|
27
|
+
</button>
|
|
28
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
29
|
+
onClick={loginByGoogle}>Google
|
|
30
|
+
</button>
|
|
31
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
32
|
+
onClick={loginByTelegram}>Telegram
|
|
33
|
+
</button>
|
|
34
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
35
|
+
onClick={() => setEmailOpen(true)}>Email
|
|
36
|
+
</button>
|
|
37
|
+
<EmailModal isOpen={emailOpen} onClose={() => setEmailOpen(false)} onBack={() => {
|
|
38
|
+
console.log('input email modal back event')
|
|
39
|
+
setEmailOpen(false)
|
|
40
|
+
}}/>
|
|
41
|
+
|
|
42
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
43
|
+
onClick={() => setLoginOpen(true)}>Modal
|
|
44
|
+
</button>
|
|
45
|
+
<LoginModal isOpen={loginOpen} onClose={() => setLoginOpen(false)}/>
|
|
46
|
+
|
|
47
|
+
</div>
|
|
48
|
+
<div className={`flex gap-5`}>
|
|
49
|
+
<input type={"text"} className={`border`} placeholder={"email"}
|
|
50
|
+
onChange={(e) => setEmail(e.target.value)} value={email}/>
|
|
51
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
52
|
+
onClick={() => getLoginEmailCode(email)}>Send
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
<div className={`flex gap-5`}>
|
|
56
|
+
<input type={"text"} className={`border`} placeholder={"code"}
|
|
57
|
+
onChange={(e) => setCode(e.target.value)} value={code}/>
|
|
58
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
59
|
+
onClick={() => loginByEmail({email, code})}>Login
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
<div className={`font-bold text-xl`}>Components</div>
|
|
63
|
+
<div className={`font-bold text-lg`}>LoginBox</div>
|
|
64
|
+
<div className={`bg-gray-100 p-10`}>
|
|
65
|
+
<div className={`bg-white`}><LoginBox/></div>
|
|
66
|
+
</div>
|
|
67
|
+
<div className={`font-bold text-lg`}>LoginPanel</div>
|
|
68
|
+
<div className={`bg-gray-100 p-10`}>
|
|
69
|
+
<div className={`bg-white`}><LoginPanel onClose={() => console.log('onLoginPanelClose')}/></div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React, {PropsWithChildren} from "react";
|
|
2
|
+
import Login from "../Login";
|
|
3
|
+
import {Hooks} from "@matchain/matchid-sdk-react";
|
|
4
|
+
|
|
5
|
+
export default function RoutePrivate({children}: PropsWithChildren) {
|
|
6
|
+
const {isLogin} = Hooks.useUserInfo()
|
|
7
|
+
|
|
8
|
+
return isLogin ? <>{children}</> : <Login/>
|
|
9
|
+
}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import {Hooks, Components, Api} from "@matchain/matchid-sdk-react"
|
|
2
2
|
import React from "react";
|
|
3
|
+
import RoutePrivate from "../components/RoutePrivate";
|
|
3
4
|
|
|
4
5
|
const {useMatchEvents, useUserInfo, useWallet} = Hooks
|
|
5
6
|
const {
|
|
6
7
|
LoginButton,
|
|
7
|
-
LoginBox,
|
|
8
|
-
LoginPanel,
|
|
9
|
-
EmailModal,
|
|
10
|
-
LoginModal,
|
|
11
8
|
UsernameModal,
|
|
12
9
|
PasswordModal,
|
|
13
10
|
Button,
|
|
14
|
-
Modal
|
|
15
11
|
} = Components
|
|
16
12
|
|
|
17
13
|
function QueryDisplay(
|
|
@@ -54,17 +50,13 @@ function LoginContent() {
|
|
|
54
50
|
bindWallet,
|
|
55
51
|
bindTelegram,
|
|
56
52
|
} = useUserInfo();
|
|
57
|
-
const {signMessage} = useWallet()
|
|
58
53
|
const [usernameOpen, setUsernameOpen] = React.useState(false)
|
|
59
54
|
const [passwordOpen, setPasswordOpen] = React.useState(false)
|
|
60
55
|
const refreshOv = async () => {
|
|
61
56
|
await refreshOverview()
|
|
62
57
|
alert('refreshed')
|
|
63
58
|
}
|
|
64
|
-
|
|
65
|
-
const res = await signMessage('hello')
|
|
66
|
-
alert(res)
|
|
67
|
-
}
|
|
59
|
+
|
|
68
60
|
return <div>
|
|
69
61
|
<h1 className={`text-2xl`}>You are already logged in</h1>
|
|
70
62
|
<div className={`text-ellipsis break-words`}>token:{token}</div>
|
|
@@ -98,9 +90,6 @@ function LoginContent() {
|
|
|
98
90
|
<button className={`bg-gray-300 p-1 rounded mr-5`}
|
|
99
91
|
onClick={bindTelegram}>Bind telegram
|
|
100
92
|
</button>
|
|
101
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
102
|
-
onClick={onSign}>Sign message
|
|
103
|
-
</button>
|
|
104
93
|
</div>
|
|
105
94
|
<button className={`bg-gray-300 p-1 rounded mr-5`}
|
|
106
95
|
onClick={refreshOv}>Refresh Overview
|
|
@@ -115,77 +104,7 @@ function LoginContent() {
|
|
|
115
104
|
|
|
116
105
|
}
|
|
117
106
|
|
|
118
|
-
function
|
|
119
|
-
const {
|
|
120
|
-
loginByWallet,
|
|
121
|
-
loginByTwitter,
|
|
122
|
-
loginByGoogle,
|
|
123
|
-
loginByEmail,
|
|
124
|
-
getLoginEmailCode,
|
|
125
|
-
loginByTelegram,
|
|
126
|
-
} = useUserInfo();
|
|
127
|
-
const [email, setEmail] = React.useState('')
|
|
128
|
-
const [code, setCode] = React.useState('')
|
|
129
|
-
const [emailOpen, setEmailOpen] = React.useState(false)
|
|
130
|
-
const [loginOpen, setLoginOpen] = React.useState(false)
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<div className={`flex flex-col gap-10`}>
|
|
134
|
-
<div className={`flex gap-5`}>
|
|
135
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
136
|
-
onClick={loginByWallet}>Wallet
|
|
137
|
-
</button>
|
|
138
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
139
|
-
onClick={loginByTwitter}>Twitter
|
|
140
|
-
</button>
|
|
141
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
142
|
-
onClick={loginByGoogle}>Google
|
|
143
|
-
</button>
|
|
144
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
145
|
-
onClick={loginByTelegram}>Telegram
|
|
146
|
-
</button>
|
|
147
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
148
|
-
onClick={() => setEmailOpen(true)}>Email
|
|
149
|
-
</button>
|
|
150
|
-
<EmailModal isOpen={emailOpen} onClose={() => setEmailOpen(false)} onBack={() => {
|
|
151
|
-
console.log('input email modal back event')
|
|
152
|
-
setEmailOpen(false)
|
|
153
|
-
}}/>
|
|
154
|
-
|
|
155
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
156
|
-
onClick={() => setLoginOpen(true)}>Modal
|
|
157
|
-
</button>
|
|
158
|
-
<LoginModal isOpen={loginOpen} onClose={() => setLoginOpen(false)}/>
|
|
159
|
-
|
|
160
|
-
</div>
|
|
161
|
-
<div className={`flex gap-5`}>
|
|
162
|
-
<input type={"text"} className={`border`} placeholder={"email"}
|
|
163
|
-
onChange={(e) => setEmail(e.target.value)} value={email}/>
|
|
164
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
165
|
-
onClick={() => getLoginEmailCode(email)}>Send
|
|
166
|
-
</button>
|
|
167
|
-
</div>
|
|
168
|
-
<div className={`flex gap-5`}>
|
|
169
|
-
<input type={"text"} className={`border`} placeholder={"code"}
|
|
170
|
-
onChange={(e) => setCode(e.target.value)} value={code}/>
|
|
171
|
-
<button className={`bg-gray-300 p-1 rounded`}
|
|
172
|
-
onClick={() => loginByEmail({email, code})}>Login
|
|
173
|
-
</button>
|
|
174
|
-
</div>
|
|
175
|
-
<div className={`font-bold text-xl`}>Components</div>
|
|
176
|
-
<div className={`font-bold text-lg`}>LoginBox</div>
|
|
177
|
-
<div className={`bg-gray-100 p-10`}>
|
|
178
|
-
<div className={`bg-white`}><LoginBox/></div>
|
|
179
|
-
</div>
|
|
180
|
-
<div className={`font-bold text-lg`}>LoginPanel</div>
|
|
181
|
-
<div className={`bg-gray-100 p-10`}>
|
|
182
|
-
<div className={`bg-white`}><LoginPanel onClose={() => console.log('onLoginPanelClose')}/></div>
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export default function Login() {
|
|
107
|
+
export default function User() {
|
|
189
108
|
useMatchEvents({
|
|
190
109
|
onLogin: (data) => {
|
|
191
110
|
console.log('useMatchEvents.onLogin', data)
|
|
@@ -197,9 +116,11 @@ export default function Login() {
|
|
|
197
116
|
console.log('useMatchEvents.onBind', data)
|
|
198
117
|
}
|
|
199
118
|
})
|
|
200
|
-
const {isLogin} = useUserInfo()
|
|
201
119
|
return <div>
|
|
202
|
-
|
|
120
|
+
<RoutePrivate>
|
|
121
|
+
<LoginContent/>
|
|
122
|
+
</RoutePrivate>
|
|
123
|
+
|
|
203
124
|
<div className={`font-bold text-lg`}>LoginButton</div>
|
|
204
125
|
|
|
205
126
|
<div className={`bg-gray-100 p-5 mt-5`}>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {Hooks} from "@matchain/matchid-sdk-react"
|
|
2
|
+
import React, {useState} from "react";
|
|
3
|
+
import {createPublicClient, http, formatUnits, parseUnits, createWalletClient, parseGwei, Account} from "viem";
|
|
4
|
+
import {useQuery} from "@tanstack/react-query";
|
|
5
|
+
import {bscTestnet} from 'viem/chains';
|
|
6
|
+
|
|
7
|
+
const {useWallet} = Hooks
|
|
8
|
+
|
|
9
|
+
export default function Wallet() {
|
|
10
|
+
const [message, setMessage] = useState('hello')
|
|
11
|
+
const [toAddress, setToAddress] = useState('0xC47b00d62cA5e08C1bb4F07C7b23770B4807D073')
|
|
12
|
+
const [toAmount, setToAmount] = useState('0.0001')
|
|
13
|
+
const [data, setToData] = useState('0x')
|
|
14
|
+
const {address, evmAccount} = useWallet()
|
|
15
|
+
const chain = bscTestnet
|
|
16
|
+
const walletClient = createWalletClient({
|
|
17
|
+
chain: chain,
|
|
18
|
+
transport: http(),
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const [hash, setHash] = useState('')
|
|
23
|
+
const [transactionSign, setTransactionSign] = useState('')
|
|
24
|
+
const [signature, setSignature] = useState('')
|
|
25
|
+
|
|
26
|
+
const publicClient = createPublicClient({
|
|
27
|
+
chain: chain,
|
|
28
|
+
transport: http(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const balanceQuery = useQuery({
|
|
32
|
+
queryKey: ['balance', address],
|
|
33
|
+
refetchInterval: 15_000,
|
|
34
|
+
queryFn: async () => {
|
|
35
|
+
return await publicClient.getBalance({address: address as `0x${string}`})
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
//to eth
|
|
39
|
+
const balanceEth = balanceQuery.data ? formatUnits(balanceQuery.data, 18) : 0
|
|
40
|
+
|
|
41
|
+
const gasPriceQuery = useQuery({
|
|
42
|
+
queryKey: ['gasPrice'],
|
|
43
|
+
refetchInterval: 15_000,
|
|
44
|
+
queryFn: async () => {
|
|
45
|
+
return await publicClient.getGasPrice()
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const onSign = async () => {
|
|
50
|
+
const res = await walletClient.signMessage({
|
|
51
|
+
message,
|
|
52
|
+
account: evmAccount as Account
|
|
53
|
+
})
|
|
54
|
+
setSignature(res)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const onSignTransaction = async () => {
|
|
58
|
+
const transaction = {
|
|
59
|
+
account:evmAccount as Account,
|
|
60
|
+
to: toAddress as `0x${string}`,
|
|
61
|
+
value: parseUnits(toAmount, 18),
|
|
62
|
+
data: data as `0x${string}`,
|
|
63
|
+
}
|
|
64
|
+
const request = await walletClient.prepareTransactionRequest(transaction)
|
|
65
|
+
const res = await walletClient.signTransaction(request)
|
|
66
|
+
setTransactionSign(res)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const onSendTransaction = async () => {
|
|
70
|
+
const res = await walletClient.sendTransaction({
|
|
71
|
+
account:evmAccount as Account,
|
|
72
|
+
to: toAddress as `0x${string}`,
|
|
73
|
+
value: parseUnits(toAmount, 18),
|
|
74
|
+
data: data as `0x${string}`,
|
|
75
|
+
})
|
|
76
|
+
setHash(res)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
return <div>
|
|
81
|
+
<div className={`text-ellipsis break-words`}>Chain:{chain.name}</div>
|
|
82
|
+
<div className={`text-ellipsis break-words`}>address:{address}</div>
|
|
83
|
+
<div className={`text-ellipsis break-words`}>balance:{balanceQuery.data?.toString()} wei/{balanceEth} eth</div>
|
|
84
|
+
<div className={`text-ellipsis break-words`}>gas price:{gasPriceQuery.data?.toString()} wei</div>
|
|
85
|
+
<div className={`flex gap-[20px]`}>
|
|
86
|
+
<input className="border" type={'text'} placeholder={'message'} value={message}
|
|
87
|
+
onChange={(e) => setMessage(e.target.value)}/>
|
|
88
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
89
|
+
onClick={onSign}>Sign message
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
92
|
+
<div>
|
|
93
|
+
Signature:{signature}
|
|
94
|
+
</div>
|
|
95
|
+
<div className="text-bold">
|
|
96
|
+
Send Transaction
|
|
97
|
+
</div>
|
|
98
|
+
<div>
|
|
99
|
+
To Address:
|
|
100
|
+
<input className="border" type={'text'} placeholder={'to address'} value={toAddress}
|
|
101
|
+
onChange={(e) => setToAddress(e.target.value)}/>
|
|
102
|
+
</div>
|
|
103
|
+
<div>
|
|
104
|
+
Amount:
|
|
105
|
+
<input className="border" type={'text'} placeholder={'amount'} value={toAmount}
|
|
106
|
+
onChange={(e) => setToAmount(e.target.value)}/>
|
|
107
|
+
</div>
|
|
108
|
+
<div>
|
|
109
|
+
Data:
|
|
110
|
+
<input className="border" type={'text'} placeholder={'data'} value={data}
|
|
111
|
+
onChange={(e) => setToData(e.target.value)}/>
|
|
112
|
+
</div>
|
|
113
|
+
<div className={`flex gap-[20px]`}>
|
|
114
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
115
|
+
onClick={onSignTransaction}>Sign
|
|
116
|
+
</button>
|
|
117
|
+
<button className={`bg-gray-300 p-1 rounded`}
|
|
118
|
+
onClick={onSendTransaction}>Send
|
|
119
|
+
</button>
|
|
120
|
+
</div>
|
|
121
|
+
<div>
|
|
122
|
+
Sign:{transactionSign}
|
|
123
|
+
</div>
|
|
124
|
+
<div>
|
|
125
|
+
TxHash:{hash}
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
</div>
|
|
130
|
+
}
|
package/example/tsconfig.json
CHANGED
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
"moduleResolution": "node", // 使用 Node.js 风格的模块解析
|
|
11
11
|
"esModuleInterop": true,
|
|
12
12
|
"skipLibCheck": true,
|
|
13
|
-
"forceConsistentCasingInFileNames": true
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"baseUrl": "./",
|
|
15
|
+
"paths": {
|
|
16
|
+
"@/*": ["src/*"]
|
|
17
|
+
}
|
|
14
18
|
},
|
|
15
19
|
"include": ["src"]
|
|
16
20
|
}
|
package/example/vite.config.ts
CHANGED