-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathindex.tsx
More file actions
114 lines (99 loc) · 3.9 KB
/
Copy pathindex.tsx
File metadata and controls
114 lines (99 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { createRoot } from "react-dom/client";
import React, { useEffect, useState } from 'react';
import { capacityOf, generateAccountFromPrivateKey, shannonToCKB, transfer, wait } from './lib';
import { Script } from '@ckb-ccc/core';
const container = document.getElementById("root");
const root = createRoot(container)
root.render(<App />);
export function App() {
// default value: first account privkey from offckb
const [privKey, setPrivKey] = useState('0x6109170b275a09ad54877b82f7d9930f88cab5717d484fb4741ae9d1dd078cd6');
const [fromAddr, setFromAddr] = useState('');
const [fromLock, setFromLock] = useState<Script>();
const [balance, setBalance] = useState('0');
// default value: second account address from offckb
const [toAddr, setToAddr] = useState('ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqt435c3epyrupszm7khk6weq5lrlyt52lg48ucew');
// default value: 62 CKB
const [amountInCKB, setAmountInCKB] = useState('62');
const [isTransferring, setIsTransferring] = useState(false);
const [txHash, setTxHash] = useState<string>();
useEffect(() => {
if (privKey) {
updateFromInfo();
}
}, [privKey]);
const updateFromInfo = async () => {
const { lockScript, address } = await generateAccountFromPrivateKey(privKey);
const capacity = await capacityOf(address);
setFromAddr(address);
setFromLock(lockScript);
setBalance(shannonToCKB(capacity).toString());
};
const onInputPrivKey = (e: React.ChangeEvent<HTMLInputElement>) => {
// Regular expression to match a valid private key with "0x" prefix
const priv = e.target.value;
const privateKeyRegex = /^0x[0-9a-fA-F]{64}$/;
const isValid = privateKeyRegex.test(priv);
if (isValid) {
setPrivKey(priv);
} else {
alert(
`Invalid private key: must start with 0x and 32 bytes length. Ensure you're using a valid private key from the offckb accounts list.`,
);
}
};
const onTransfer = async () => {
setIsTransferring(true);
const txHash = await transfer(toAddr, amountInCKB, privKey).catch(alert);
// We can wait for this txHash to be on-chain so that we can trigger the UI/UX updates including balance.
if(txHash){
setTxHash(txHash);
// wait 10 seconds for tx confirm
// the right way to do this is to use get_transaction rpc but here we just keep it simple
await wait(10);
await updateFromInfo();
}
setIsTransferring(false);
}
const enabled = +amountInCKB > 61 && +balance > +amountInCKB && toAddr.length > 0 && !isTransferring;
const amountTip =
amountInCKB.length > 0 && +amountInCKB < 61 ? (
<span>
amount must larger than 61 CKB, see{' '}
<a href="https://docs.nervos.org/docs/integrate-wallets/intro-to-wallets/#requirements-for-ckb-transfers">why</a>
</span>
) : null;
return (
<div>
<h1>View and Transfer Balance</h1>
<label htmlFor="private-key">Private Key: </label>
<input id="private-key" type="text" value={privKey} onChange={onInputPrivKey} />
<ul>
<li>CKB Address: {fromAddr}</li>
<li>
Current lock script:
<pre>{JSON.stringify(fromLock, null, 2)}</pre>
</li>
<li>Total capacity: {balance} CKB</li>
</ul>
<label htmlFor="to-address">Transfer to Address: </label>
<input id="to-address" type="text" value={toAddr} onChange={(e) => setToAddr(e.target.value)} />
<br />
<label htmlFor="amount">Amount</label>
<input id="amount" type="number" value={amountInCKB} onChange={(e) => setAmountInCKB(e.target.value)} />CKB{" "}
<small>Tx fee: 0.001 CKB</small>
<br />
<small style={{ color: 'red' }}>{amountTip}</small>
<br />
<br />
<button
disabled={!enabled}
onClick={onTransfer}
>
Transfer
</button>
{txHash && <div>tx hash: {txHash}</div>}
</div>
);
}