SJCL
This commit is contained in:
parent
accaa7f6ff
commit
1548975971
@ -7,7 +7,7 @@
|
|||||||
<title>Vite + React</title>
|
<title>Vite + React</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root" class="h-screen w-screen"></div>
|
||||||
<script type="module" src="/src/main.jsx"></script>
|
<script type="module" src="/src/main.jsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
32
src/App.jsx
32
src/App.jsx
@ -1,7 +1,27 @@
|
|||||||
import './App.css'
|
/*eslint-disable */
|
||||||
|
import Login from "./Screens/Login.jsx";
|
||||||
function App() {
|
import { useState, useEffect } from "react";
|
||||||
return()
|
import MainApp from "./Screens/MainApp.jsx";
|
||||||
|
import sjcl from "sjcl";
|
||||||
|
export default function App() {
|
||||||
|
const colors = { primary: "bg-blue-200", secondary: "bg-emerald-400" };
|
||||||
|
const [keys, setKeys] = useState({ public: "", private: "" });
|
||||||
|
if (keys.private !== "") {
|
||||||
|
console.log("heykj");
|
||||||
|
console.log(keys.private);
|
||||||
|
window.localStorage.setItem("private", keys.private);
|
||||||
|
} else {
|
||||||
|
if (window.localStorage.getItem("private") !== null) {
|
||||||
|
console.log(window.localStorage.getItem("private"));
|
||||||
|
setKeys({
|
||||||
|
private: window.localStorage.getItem("private"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(keys);
|
||||||
|
return keys.private.length < 10 ? (
|
||||||
|
<Login colors={colors} setKeys={setKeys} />
|
||||||
|
) : (
|
||||||
|
<MainApp colors={colors} keys={keys} setKeys={setKeys} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
|
||||||
|
46
src/Components/Header.jsx
Normal file
46
src/Components/Header.jsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*eslint-disable */
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import getAccount from "../Scripts/Testnet";
|
||||||
|
import sjcl from "sjcl";
|
||||||
|
function desprorr2(encripted) {
|
||||||
|
var parsedMessage = JSON.parse(encripted);
|
||||||
|
var encryptedMessageWithoutParameters = JSON.stringify(parsedMessage);
|
||||||
|
|
||||||
|
//Decrypt
|
||||||
|
var parsedMessage = JSON.parse(encryptedMessageWithoutParameters);
|
||||||
|
var messageWithParameters = JSON.stringify(parsedMessage);
|
||||||
|
var decryptedMessage = sjcl.decrypt("arstotzka", messageWithParameters);
|
||||||
|
return decryptedMessage;
|
||||||
|
}
|
||||||
|
export default function Header({ keys, setKeys }) {
|
||||||
|
const [balance, setBalance] = useState(null);
|
||||||
|
const desprivate = desprorr2(keys.private);
|
||||||
|
console.log(desprivate);
|
||||||
|
if (balance === null) {
|
||||||
|
getAccount(desprivate).then((account) => {
|
||||||
|
if (account.balances[0].asset_code === "BLC") {
|
||||||
|
setBalance(Math.trunc(account.balances[0].balance * 100) / 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleLogout() {
|
||||||
|
setKeys({
|
||||||
|
public: "r",
|
||||||
|
private: "r",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row pt-5 gap-[20%] h-32 bg-blue-300 ">
|
||||||
|
<div className="bg-blue-400 w-[25rem] self-center flex flex-col justify-center rounded-xl ml-[45%]">
|
||||||
|
<h1 className="text-white text-5xl self-center">Balance Actual:</h1>
|
||||||
|
<h1 className=" text-yellow-200 text-5xl self-center">{balance}</h1>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="w-[7rem] h-[3rem] bg-teal-600 text-white rounded-3xl self-center"
|
||||||
|
onClick={handleLogout}
|
||||||
|
>
|
||||||
|
Cerrar Sesion
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
51
src/Components/Pay.jsx
Normal file
51
src/Components/Pay.jsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*eslint-disable */
|
||||||
|
import { send } from "../Scripts/Testnet";
|
||||||
|
import sjcl from "sjcl";
|
||||||
|
function desprorr2(encripted) {
|
||||||
|
var parsedMessage = JSON.parse(encripted);
|
||||||
|
var encryptedMessageWithoutParameters = JSON.stringify(parsedMessage);
|
||||||
|
|
||||||
|
//Decrypt
|
||||||
|
var parsedMessage = JSON.parse(encryptedMessageWithoutParameters);
|
||||||
|
var messageWithParameters = JSON.stringify(parsedMessage);
|
||||||
|
var decryptedMessage = sjcl.decrypt("arstotzka", messageWithParameters);
|
||||||
|
return decryptedMessage;
|
||||||
|
}
|
||||||
|
export default function Pay({ keys }) {
|
||||||
|
function handleSend() {
|
||||||
|
console.log(keys);
|
||||||
|
const amount = document.getElementById("amount").value;
|
||||||
|
const to = document.getElementById("to").value;
|
||||||
|
send(amount, desprorr2(keys.private), to);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="h-3/6 w-2/6 bg-teal-400 self-center ml-[10rem] rounded-2xl flex flex-col gap-5 justify-center">
|
||||||
|
<label htmlFor="send2" className="font-bold text-3xl self-center">
|
||||||
|
Send to:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="send2"
|
||||||
|
id="to"
|
||||||
|
className="h-[2rem] w-3/6 self-center border-4 border-teal-200 rounded-md"
|
||||||
|
placeholder="Example: GDY2CP7XLBIY65YX7KS72X7JCZJVJ3AEPEEFTW3TYPLGDRWEZKAC7NR3"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
<label htmlFor="amount" className="font-bold text-3xl self-center">
|
||||||
|
BLC Amount:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="amount"
|
||||||
|
name="amount"
|
||||||
|
className="h-[2rem] w-3/6 self-center border-4 border-teal-200 rounded-md"
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
name="submit"
|
||||||
|
type="submit"
|
||||||
|
value="Send"
|
||||||
|
className="rounded bg-blue-500 text-white px-4 py-2 cursor-pointer w-3/6 self-center"
|
||||||
|
onClick={handleSend}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
74
src/Components/Transactions.jsx
Normal file
74
src/Components/Transactions.jsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*eslint-disable */
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import getAccount from "../Scripts/Testnet";
|
||||||
|
import sjcl from "sjcl";
|
||||||
|
function desprorr2(encripted) {
|
||||||
|
var parsedMessage = JSON.parse(encripted);
|
||||||
|
var encryptedMessageWithoutParameters = JSON.stringify(parsedMessage);
|
||||||
|
|
||||||
|
//Decrypt
|
||||||
|
var parsedMessage = JSON.parse(encryptedMessageWithoutParameters);
|
||||||
|
var messageWithParameters = JSON.stringify(parsedMessage);
|
||||||
|
var decryptedMessage = sjcl.decrypt("arstotzka", messageWithParameters);
|
||||||
|
return decryptedMessage;
|
||||||
|
}
|
||||||
|
export default function Transactions({ keys }) {
|
||||||
|
const [operations, setOperations] = useState([]);
|
||||||
|
const [publickey, setPublickey] = useState("");
|
||||||
|
const desprivate = desprorr2(keys.private);
|
||||||
|
useEffect(() => {
|
||||||
|
getAccount(desprivate).then((account) => {
|
||||||
|
const newOperations = [];
|
||||||
|
setPublickey(account.account_id);
|
||||||
|
console.log(publickey);
|
||||||
|
account.payments().then((pay) => {
|
||||||
|
pay.records.forEach((element) => {
|
||||||
|
newOperations.push(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
setOperations(newOperations.reverse());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
console.log(operations);
|
||||||
|
|
||||||
|
/*getAccount(keys.private).then((account) =>
|
||||||
|
account.transactions().then((tran) => console.log(tran.records[0]))
|
||||||
|
);*/
|
||||||
|
return (
|
||||||
|
<div className=" w-[32%] h-5/6 bg-teal-200 shadow-xl rounded-xl flex flex-col gap-5 overflow-scroll mt-10">
|
||||||
|
{operations.map((operation) => (
|
||||||
|
<div className="bg-teal-400 flex flex-col gap-2 rounded-lg w-[95%] self-center mt-5">
|
||||||
|
<h1 className="text-xl text-yellow-700 font-bold">
|
||||||
|
{operation.type}:
|
||||||
|
</h1>
|
||||||
|
<h1 className="font-semibold">{operation.amount}</h1>
|
||||||
|
{operation.funder ? (
|
||||||
|
<h1 className="font-semibold">By: {operation.funder}</h1>
|
||||||
|
) : null}
|
||||||
|
{operation.asset_code ? (
|
||||||
|
<h1 className="font-semibold">Token: {operation.asset_code}</h1>
|
||||||
|
) : null}
|
||||||
|
{operation.from ? (
|
||||||
|
operation.from === publickey ? (
|
||||||
|
<h1 className="font-semibold">
|
||||||
|
from: <span className="text-red-400 text-xl">Me</span>
|
||||||
|
</h1>
|
||||||
|
) : (
|
||||||
|
<h1 className="font-semibold">from: {operation.from}</h1>
|
||||||
|
)
|
||||||
|
) : null}
|
||||||
|
{operation.to ? (
|
||||||
|
operation.to === publickey ? (
|
||||||
|
<h1 className="font-semibold">
|
||||||
|
to: <span className="text-red-400 text-xl">Me</span>
|
||||||
|
</h1>
|
||||||
|
) : (
|
||||||
|
<h1 className="font-semibold">to: {operation.to}</h1>
|
||||||
|
)
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
51
src/Screens/Login.jsx
Normal file
51
src/Screens/Login.jsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*eslint-disable */
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import sjcl from "sjcl";
|
||||||
|
export default function Login({ colors, setKeys }) {
|
||||||
|
function handleSubmit() {
|
||||||
|
const privatekey = document.getElementById("privatekey").value;
|
||||||
|
setKeys({
|
||||||
|
private: sjcl.encrypt("arstotzka", privatekey),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={colors.primary + " w-full h-full flex flex-col"}>
|
||||||
|
<h1 className="text-black text-opacity-70 text-6xl self-center mt-[10rem] shadow-blue-300 shadow-sm">
|
||||||
|
BLC Wallet Login
|
||||||
|
</h1>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
colors.secondary +
|
||||||
|
" flex w-2/6 min-w-[20rem] min-h-[14rem] h-2/6 mt-[2rem] justify-center rounded-lg self-center"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col justify-center gap-5 w-3/6 ">
|
||||||
|
<div className="bg-blue-400 text-center rounded-lg h-10 flex flex-col justify-center">
|
||||||
|
<label
|
||||||
|
htmlFor="privatekey"
|
||||||
|
className="text-white text-2xl self-center"
|
||||||
|
>
|
||||||
|
Your Private Key:
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
name="privatekey"
|
||||||
|
id="privatekey"
|
||||||
|
className="h-8 rounded-sm"
|
||||||
|
type="password"
|
||||||
|
placeholder=" Starts with 'S'"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
name="submit"
|
||||||
|
type="submit"
|
||||||
|
value="Enter"
|
||||||
|
className={
|
||||||
|
"rounded bg-blue-500 text-white px-4 py-2 cursor-pointer"
|
||||||
|
}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
15
src/Screens/MainApp.jsx
Normal file
15
src/Screens/MainApp.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*eslint-disable */
|
||||||
|
import Header from "../Components/Header";
|
||||||
|
import Pay from "../Components/Pay";
|
||||||
|
import Transactions from "../Components/Transactions";
|
||||||
|
export default function MainApp({ colors, keys, setKeys }) {
|
||||||
|
return (
|
||||||
|
<div className={colors.primary + " w-full h-full"}>
|
||||||
|
<Header keys={keys} setKeys={setKeys} />
|
||||||
|
<div className="flex flex-row w-full h-5/6">
|
||||||
|
<Transactions keys={keys} />
|
||||||
|
<Pay keys={keys} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
52
src/Scripts/Testnet.js
Normal file
52
src/Scripts/Testnet.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*Public Key
|
||||||
|
GDY2CP7XLBIY65YX7KS72X7JCZJVJ3AEPEEFTW3TYPLGDRWEZKAC7NR3
|
||||||
|
Secret Key
|
||||||
|
SAM4KRGZ4YTAQV3XK3FRKVHZV77AA37KSYZLKZ4OZSX3SBWR6C6NYS4M
|
||||||
|
*/
|
||||||
|
import StellarSdk from 'stellar-sdk'
|
||||||
|
const server = new StellarSdk.Server('https://horizon-testnet.stellar.org'); // const server = new StellarSdk.Server('https://horizon.stellar.org');
|
||||||
|
const fee = await server.fetchBaseFee();
|
||||||
|
export default function getAccount(privatekey){
|
||||||
|
const keypair = StellarSdk.Keypair.fromSecret(privatekey)
|
||||||
|
return server.loadAccount(keypair.publicKey())
|
||||||
|
}
|
||||||
|
export function send(amount, privatekey, destination){
|
||||||
|
const keypair = StellarSdk.Keypair.fromSecret(privatekey)
|
||||||
|
server.loadAccount(keypair.publicKey()).then(account => {
|
||||||
|
console.log(account)
|
||||||
|
const transaction = new StellarSdk.TransactionBuilder(account, {fee, networkPassphrase: StellarSdk.Networks.TESTNET})
|
||||||
|
// Add a payment operation to the transaction
|
||||||
|
.addOperation(StellarSdk.Operation.payment({
|
||||||
|
destination: destination,
|
||||||
|
// The term native asset refers to lumens
|
||||||
|
asset: new StellarSdk.Asset("BLC", "GBPKUSD5ZGMEXCS5YW7WAOC2QJSJLEX6LHGUTJIMDYYPFLPOT6GYFNNX"),
|
||||||
|
// Specify 350.1234567 lumens. Lumens are divisible to seven digits past
|
||||||
|
// the decimal. They are represented in JS Stellar SDK in string format
|
||||||
|
// to avoid errors from the use of the JavaScript Number data structure.
|
||||||
|
amount: amount,
|
||||||
|
}))
|
||||||
|
// Make this transaction valid for the next 30 seconds only
|
||||||
|
.setTimeout(30)
|
||||||
|
// Uncomment to add a memo (https://www.stellar.org/developers/learn/concepts/transactions.html)
|
||||||
|
// .addMemo(StellarSdk.Memo.text('Hello world!'))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Sign this transaction with the secret key
|
||||||
|
// NOTE: signing is transaction is network specific. Test network transactions
|
||||||
|
// won't work in the public network. To switch networks, use the Network object
|
||||||
|
// as explained above (look for StellarSdk.Network).
|
||||||
|
transaction.sign(keypair)
|
||||||
|
try {
|
||||||
|
server.submitTransaction(transaction);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('An error has occured:');
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Let's see the XDR (encoded in base64) of the transaction we just built
|
||||||
|
|
||||||
|
// Submit the transaction to the Horizon server. The Horizon server will then
|
||||||
|
// submit the transaction into the network for us.
|
||||||
|
|
||||||
|
}
|
13
src/main.jsx
13
src/main.jsx
@ -1,9 +1,10 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
import ReactDOM from 'react-dom/client'
|
import "./App.css";
|
||||||
import App from './App.jsx'
|
import ReactDOM from "react-dom/client";
|
||||||
|
import App from "./App.jsx";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<App />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>
|
||||||
)
|
);
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react-swc'
|
import react from '@vitejs/plugin-react-swc'
|
||||||
|
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
optimizeDeps: {
|
||||||
|
esbuildOptions: {
|
||||||
|
// Node.js global to browser globalThis
|
||||||
|
define: {
|
||||||
|
global: 'window'
|
||||||
|
},
|
||||||
|
// Enable esbuild polyfill plugins
|
||||||
|
plugins: [
|
||||||
|
NodeGlobalsPolyfillPlugin({
|
||||||
|
buffer: true
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user