Skip to content

Commit 24a1645

Browse files
authored
Merge pull request #70 from matiasbenary/feat/add-Sui-network
Feat/add sui network
2 parents f996876 + bc14519 commit 24a1645

File tree

3 files changed

+247
-0
lines changed

3 files changed

+247
-0
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@ethereumjs/common": "^4.3.0",
1515
"@ethereumjs/tx": "^5.3.0",
1616
"@ethereumjs/util": "^9.0.3",
17+
"@mysten/sui": "^1.30.4",
1718
"@near-wallet-selector/bitte-wallet": "^8.9.13",
1819
"@near-wallet-selector/core": "^8.9.13",
1920
"@near-wallet-selector/here-wallet": "^8.9.13",
@@ -27,7 +28,11 @@
2728
"bitcoinjs-lib": "^6.1.5",
2829
"bn.js": "^5.2.1",
2930
"bs58check": "^3.0.1",
31+
<<<<<<< feat/add-Sui-network
32+
"chainsig.js": "^1.1.7",
33+
=======
3034
"chainsig.js": "^1.1.8",
35+
>>>>>>> main
3136
"elliptic": "^6.5.5",
3237
"ethers": "^6.11.1",
3338
"hash.js": "^1.1.7",

src/App.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { BitcoinView } from './components/Bitcoin';
66
import { explorerForChain, MPC_CONTRACT, RPCforChain } from './config';
77
import { useWalletSelector } from '@near-wallet-selector/react-hook';
88
import { SolanaView } from './components/Solana';
9+
import { SuiView } from './components/Sui';
910
import { AptosView } from './components/Aptos';
1011
import { XRPView } from './components/XRP';
1112

@@ -68,6 +69,7 @@ function App() {
6869
<option value='base'> Ξ Base </option>
6970
<option value='btc'> ₿ BTC </option>
7071
<option value='sol'> 🪙 Solana </option>
72+
<option value='sui'> 🪙 Sui </option>
7173
<option value='apt'> Ξ Aptos </option>
7274
<option value='xrp'> 🪙 XRP </option>
7375
</select>
@@ -93,6 +95,9 @@ function App() {
9395
{chain === 'xrp' && (
9496
<XRPView props={{setStatus}}></XRPView>
9597
)}
98+
{chain === 'sui' && (
99+
<SuiView props={{setStatus}} />
100+
)}
96101
</div>
97102
</div>
98103
)}

src/components/Sui.jsx

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import PropTypes from "prop-types";
2+
3+
import { useWalletSelector } from "@near-wallet-selector/react-hook";
4+
import { useEffect, useState } from "react";
5+
import { useDebounce } from "../hooks/debounce";
6+
import { SIGNET_CONTRACT } from "../config";
7+
import { chainAdapters } from "chainsig.js";
8+
import { getFullnodeUrl, SuiClient } from '@mysten/sui/client'
9+
import { Transaction } from '@mysten/sui/transactions'
10+
import { bigIntToDecimal } from "../utils/bigIntToDecimal";
11+
import { decimalToBigInt } from "../utils/decimalToBigInt";
12+
13+
const rpcUrl = getFullnodeUrl('testnet')
14+
const suiClient = new SuiClient({ url: rpcUrl })
15+
16+
const Sui = new chainAdapters.sui.SUI({
17+
client: suiClient,
18+
contract: SIGNET_CONTRACT,
19+
rpcUrl: rpcUrl,
20+
})
21+
22+
export function SuiView({ props: { setStatus } }) {
23+
const { signedAccountId, signAndSendTransactions } = useWalletSelector();
24+
25+
const [receiver, setReceiver] = useState("0x202fc1c421cbd6d84d632d62de50b90c1cf5564c36422a1cd00b5448b9e3d29f");
26+
const [amount, setAmount] = useState(1);
27+
const [loading, setLoading] = useState(false);
28+
const [step, setStep] = useState("request");
29+
const [signedTransaction, setSignedTransaction] = useState(null);
30+
const [senderAddress, setSenderAddress] = useState("");
31+
const [senderPK, setSenderPK] = useState("");
32+
33+
const [derivation, setDerivation] = useState("sui-1");
34+
const derivationPath = useDebounce(derivation, 500);
35+
36+
useEffect(() => {
37+
setSenderAddress("Waiting for you to stop typing...");
38+
}, [derivation]);
39+
40+
useEffect(() => {
41+
setSuiAddress();
42+
43+
async function setSuiAddress() {
44+
setStatus("Querying your address and balance");
45+
setSenderAddress(`Deriving address from path ${derivationPath}...`);
46+
47+
const { address, publicKey } = await Sui.deriveAddressAndPublicKey(signedAccountId, derivationPath);
48+
49+
setSenderPK(publicKey);
50+
setSenderAddress(address);
51+
52+
const balance = await Sui.getBalance(address);
53+
54+
setStatus(
55+
`Your Sui address is: ${address}, balance: ${bigIntToDecimal(balance.balance, balance.decimals)} SUI`
56+
);
57+
}
58+
}, [signedAccountId, derivationPath, setStatus]);
59+
60+
async function chainSignature() {
61+
setStatus("🏗️ Creating transaction");
62+
63+
const tx = new Transaction()
64+
65+
const [coin] = tx.splitCoins(tx.gas, [decimalToBigInt(amount, 9)])
66+
67+
tx.transferObjects(
68+
[coin],
69+
receiver
70+
)
71+
tx.setSender(senderAddress)
72+
73+
const { hashesToSign, transaction } = await Sui.prepareTransactionForSigning(tx)
74+
75+
76+
setStatus(
77+
"🕒 Asking MPC to sign the transaction, this might take a while..."
78+
);
79+
80+
try {
81+
const rsvSignatures = await SIGNET_CONTRACT.sign({
82+
payloads: hashesToSign,
83+
path: derivationPath,
84+
keyType: "Eddsa",
85+
signerAccount: {
86+
accountId: signedAccountId,
87+
signAndSendTransactions
88+
}
89+
});
90+
91+
if (!rsvSignatures[0] || !rsvSignatures[0].signature) {
92+
throw new Error("Failed to sign transaction");
93+
}
94+
95+
const txSerialized = Sui.finalizeTransactionSigning({
96+
transaction,
97+
rsvSignatures: rsvSignatures[0],
98+
publicKey: senderPK
99+
})
100+
101+
setStatus("✅ Signed payload ready to be relayed to the Sui network");
102+
setSignedTransaction(txSerialized);
103+
setStep("relay");
104+
} catch (e) {
105+
console.log(e);
106+
setStatus(`❌ Error: ${e.message}`);
107+
setLoading(false);
108+
}
109+
}
110+
111+
async function relayTransaction() {
112+
setLoading(true);
113+
setStatus(
114+
"🔗 Relaying transaction to the Sui network... this might take a while"
115+
);
116+
117+
try {
118+
119+
const txHash = await Sui.broadcastTx(signedTransaction);
120+
121+
setStatus(
122+
<>
123+
<a
124+
href={`https://suiscan.xyz/testnet/tx/${txHash.hash}`}
125+
target="_blank"
126+
>
127+
{" "}
128+
✅ Successfully Broadcasted{" "}
129+
</a>
130+
</>
131+
);
132+
} catch (e) {
133+
setStatus(`❌ Error: ${e.message}`);
134+
}
135+
136+
setStep("request");
137+
setLoading(false);
138+
}
139+
140+
const UIChainSignature = async () => {
141+
setLoading(true);
142+
await chainSignature();
143+
setLoading(false);
144+
};
145+
146+
return (<>
147+
<div className="alert alert-info text-center" role="alert">
148+
You are working with <strong>DevTest</strong>.
149+
<br />
150+
You can get funds from the faucet:
151+
<a
152+
href="https://faucet.sui.io/"
153+
target="_blank"
154+
rel="noopener noreferrer"
155+
className="alert-link"
156+
>
157+
faucet.sui.io/
158+
</a>
159+
</div>
160+
<div className="row my-3">
161+
<label className="col-sm-2 col-form-label col-form-label-sm">
162+
Path:
163+
</label>
164+
<div className="col-sm-10">
165+
<input
166+
type="text"
167+
className="form-control form-control-sm"
168+
value={derivation}
169+
onChange={(e) => setDerivation(e.target.value)}
170+
disabled={loading}
171+
/>
172+
<div className="form-text" id="eth-sender">
173+
{" "}
174+
{senderAddress}{" "}
175+
</div>
176+
</div>
177+
</div>
178+
<div className="row mb-3">
179+
<label className="col-sm-2 col-form-label col-form-label-sm">To:</label>
180+
<div className="col-sm-10">
181+
<input
182+
type="text"
183+
className="form-control form-control-sm"
184+
value={receiver}
185+
onChange={(e) => setReceiver(e.target.value)}
186+
disabled={loading}
187+
/>
188+
</div>
189+
</div>
190+
<div className="row mb-3">
191+
<label className="col-sm-2 col-form-label col-form-label-sm">
192+
Amount:
193+
</label>
194+
<div className="col-sm-10">
195+
<input
196+
type="number"
197+
className="form-control form-control-sm"
198+
value={amount}
199+
onChange={(e) => setAmount(e.target.value)}
200+
step="0.1"
201+
min="0"
202+
disabled={loading}
203+
/>
204+
<div className="form-text"> sui units </div>
205+
</div>
206+
</div>
207+
208+
<div className="text-center mt-3">
209+
{step === "request" && (
210+
<button
211+
className="btn btn-primary text-center"
212+
onClick={UIChainSignature}
213+
disabled={loading}
214+
>
215+
{" "}
216+
Request Signature{" "}
217+
</button>
218+
)}
219+
{step === "relay" && (
220+
<button
221+
className="btn btn-success text-center"
222+
onClick={relayTransaction}
223+
disabled={loading}
224+
>
225+
{" "}
226+
Relay Transaction{" "}
227+
</button>
228+
)}
229+
</div>
230+
</>)
231+
}
232+
233+
SuiView.propTypes = {
234+
props: PropTypes.shape({
235+
setStatus: PropTypes.func.isRequired,
236+
}).isRequired,
237+
};

0 commit comments

Comments
 (0)