Changed folder structure

This commit is contained in:
AlexanderBuzz
2023-07-31 19:47:33 +02:00
parent cb629d1004
commit 729687b75f
38 changed files with 147 additions and 43 deletions

View File

@@ -0,0 +1,94 @@
const { app, BrowserWindow, ipcMain } = require('electron')
const fs = require("fs");
const path = require('path')
const xrpl = require("xrpl")
const { initialize, subscribe, saveSaltedSeed, loadSaltedSeed } = require('../library/5_helpers')
const { sendXrp } = require('../library/7_helpers')
const { verify } = require('../library/8_helpers')
const TESTNET_URL = "wss://s.altnet.rippletest.net:51233"
const WALLET_DIR = 'Wallet'
const createWindow = () => {
const appWindow = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
preload: path.join(__dirname, 'view', '8_preload.js'),
},
})
appWindow.loadFile(path.join(__dirname, 'view', '8_domain-verification.html'))
return appWindow
}
const main = async () => {
const appWindow = createWindow()
if (!fs.existsSync(WALLET_DIR)) {
// Create Wallet directory in case it does not exist yet
fs.mkdirSync(path.join(__dirname, WALLET_DIR));
}
let seed = null;
ipcMain.on('seed-entered', async (event, providedSeed) => {
seed = providedSeed
appWindow.webContents.send('open-password-dialog')
})
ipcMain.on('password-entered', async (event, password) => {
if (!fs.existsSync(path.join(__dirname, WALLET_DIR , 'seed.txt'))) {
saveSaltedSeed('../' + WALLET_DIR, seed, password)
} else {
seed = loadSaltedSeed('../' + WALLET_DIR, password)
}
const wallet = xrpl.Wallet.fromSeed(seed)
const client = new xrpl.Client(TESTNET_URL)
await client.connect()
await subscribe(client, wallet, appWindow)
await initialize(client, wallet, appWindow)
ipcMain.on('send-xrp-action', (event, paymentData) => {
sendXrp(paymentData, client, wallet).then((result) => {
appWindow.webContents.send('send-xrp-transaction-finish', result)
})
})
ipcMain.on('destination-account-change', (event, destinationAccount) => {
verify(destinationAccount, client).then((result) => {
appWindow.webContents.send('update-domain-verification-data', result)
})
})
})
ipcMain.on('request-seed-change', (event) => {
fs.rmSync(path.join(__dirname, WALLET_DIR , 'seed.txt'))
fs.rmSync(path.join(__dirname, WALLET_DIR , 'salt.txt'))
appWindow.webContents.send('open-seed-dialog')
})
// We have to wait for the application frontend to be ready, otherwise
// we might run into a race condition and the ope-dialog events
// get triggered before the callbacks are attached
appWindow.once('ready-to-show', () => {
// If there is no seed present yet, ask for it, otherwise query for the password
// for the seed that has been saved
if (!fs.existsSync(path.join(__dirname, WALLET_DIR, 'seed.txt'))) {
appWindow.webContents.send('open-seed-dialog')
} else {
appWindow.webContents.send('open-password-dialog')
}
})
}
app.whenReady().then(main)

View File

@@ -0,0 +1,159 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>XRPL Wallet Tutorial (JavaScript / Electron)</title>
<link rel="stylesheet" href="../../bootstrap/bootstrap.min.css"/>
<link rel="stylesheet" href="../../bootstrap/custom.css"/>
</head>
<body>
<main class="bg-light">
<div class="sidebar d-flex flex-column flex-shrink-0 p-3 text-white bg-dark">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-white text-decoration-none">
<img class="logo" height="40"/>
</a>
<hr>
<ul class="nav nav-pills flex-column mb-auto" role="tablist">
<li class="nav-item">
<button class="nav-link active" id="dashboard-tab" data-bs-toggle="tab" data-bs-target="#dashboard"
type="button" role="tab" aria-controls="dashboard" aria-selected="true">
Dashboard
</button>
</li>
<li>
<button class="nav-link" data-bs-toggle="tab" id="transactions-tab" data-bs-target="#transactions"
type="button" role="tab" aria-controls="transactions" aria-selected="false">
Transactions
</button>
</li>
</ul>
</div>
<div class="divider"></div>
<div class="main-content tab-content d-flex flex-column flex-shrink-0 p-3">
<div class="header border-bottom">
<h3>
Build a XRPL Wallet
<small class="text-muted">- Part 8/8</small>
</h3>
<button type="button" class="btn btn-primary" id="send-xrp-modal-button">
Send XRP
</button>
</div>
<div class="tab-pane fade show active" id="dashboard" role="tabpanel" aria-labelledby="dashboard-tab">
<h3>Account:</h3>
<ul class="list-group">
<li class="list-group-item">Classic Address: <strong id="account-address-classic"></strong></li>
<li class="list-group-item">X-Address: <strong id="account-address-x"></strong></li>
<li class="list-group-item">XRP Balance: <strong id="account-balance"></strong></li>
<li class="list-group-item">XRP Reserved: <strong id="account-reserve"></strong></li>
</ul>
<div class="spacer"></div>
<h3>
Ledger
<small class="text-muted">(Latest validated ledger)</small>
</h3>
<ul class="list-group">
<li class="list-group-item">Ledger Index: <strong id="ledger-index"></strong></li>
<li class="list-group-item">Ledger Hash: <strong id="ledger-hash"></strong></li>
<li class="list-group-item">Close Time: <strong id="ledger-close-time"></strong></li>
</ul>
</div>
<div class="tab-pane fade" id="transactions" role="tabpanel" aria-labelledby="transactions-tab">
<h3>Transactions:</h3>
<table id="tx-table" class="table">
<thead>
<tr>
<th>Confirmed</th>
<th>Type</th>
<th>From</th>
<th>To</th>
<th>Value Delivered</th>
<th>Hash</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="modal fade" id="send-xrp-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="send-xrp-modal-label">Send XRP</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<div class="accountVerificationIndicator">
<span>Verification status:</span>
</div>
<input type="text" class="form-control" value="rP4zcp52pa7ZjhjtU9LrnFcitBUadNW8Xz"
id="input-destination-address">
<span class="input-group-text">To (Address)</span>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" value="12345"
id="input-destination-tag">
<span class="input-group-text">Destination Tag</span>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" value="100"
id="input-xrp-amount">
<span class="input-group-text">Amount of XRP</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="send-xrp-submit-button">Send</button>
</div>
</div>
</div>
</div>
</main>
<dialog id="seed-dialog">
<form method="dialog">
<div>
<label for="seed-input">Enter seed:</label>
<input type="text" id="seed-input" name="seed-input" />
</div>
<div>
<button type="submit">Confirm</button>
</div>
</form>
</dialog>
<dialog id="password-dialog">
<form method="dialog">
<div>
<label for="password-input">Enter password (min-length 5):</label><br />
<input type="text" id="password-input" name="password-input" />
</div>
<div>
<button type="button">Change Seed</button>
<button type="submit">Submit</button>
</div>
</form>
</dialog>
</body>
<script src="../../bootstrap/bootstrap.bundle.min.js"></script>
<script src="8_renderer.js"></script>
</html>

View File

@@ -0,0 +1,44 @@
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
onOpenSeedDialog: (callback) => {
ipcRenderer.on('open-seed-dialog', callback)
},
onEnterSeed: (seed) => {
ipcRenderer.send('seed-entered', seed)
},
onOpenPasswordDialog: (callback) => {
ipcRenderer.on('open-password-dialog', callback)
},
onEnterPassword: (password) => {
ipcRenderer.send('password-entered', password)
},
requestSeedChange: () => {
ipcRenderer.send('request-seed-change')
},
onUpdateLedgerData: (callback) => {
ipcRenderer.on('update-ledger-data', callback)
},
onUpdateAccountData: (callback) => {
ipcRenderer.on('update-account-data', callback)
},
onUpdateTransactionData: (callback) => {
ipcRenderer.on('update-transaction-data', callback)
},
onClickSendXrp: (paymentData) => {
ipcRenderer.send('send-xrp-action', paymentData)
},
onSendXrpTransactionFinish: (callback) => {
ipcRenderer.on('send-xrp-transaction-finish', callback)
},
// Step 8 code additions - start
onDestinationAccountChange: (callback) => {
ipcRenderer.send('destination-account-change', callback)
},
onUpdateDomainVerificationData: (callback) => {
ipcRenderer.on('update-domain-verification-data', callback)
},
// Step 8 code additions - start
})

View File

@@ -0,0 +1,113 @@
window.electronAPI.onOpenSeedDialog((_event) => {
const seedDialog = document.getElementById('seed-dialog');
const seedInput = seedDialog.querySelector('input');
const submitButton = seedDialog.querySelector('button[type="submit"]');
submitButton.addEventListener('click', () => {
const seed = seedInput.value;
window.electronAPI.onEnterSeed(seed)
seedDialog.close()
});
seedDialog.showModal()
})
window.electronAPI.onOpenPasswordDialog((_event) => {
const passwordDialog = document.getElementById('password-dialog')
const passwordInput = passwordDialog.querySelector('input')
const submitButton = passwordDialog.querySelector('button[type="submit"]')
const changeSeedButton = passwordDialog.querySelector('button[type="button"]')
submitButton.addEventListener('click', () => {
const password = passwordInput.value
window.electronAPI.onEnterPassword(password)
passwordDialog.close()
});
changeSeedButton.addEventListener('click', () => {
passwordDialog.close()
window.electronAPI.requestSeedChange()
});
passwordDialog.showModal()
});
const ledgerIndexEl = document.getElementById('ledger-index')
const ledgerHashEl = document.getElementById('ledger-hash')
const ledgerCloseTimeEl = document.getElementById('ledger-close-time')
window.electronAPI.onUpdateLedgerData((_event, ledger) => {
ledgerIndexEl.innerText = ledger.ledgerIndex
ledgerHashEl.innerText = ledger.ledgerHash
ledgerCloseTimeEl.innerText = ledger.ledgerCloseTime
})
const accountAddressClassicEl = document.getElementById('account-address-classic')
const accountAddressXEl = document.getElementById('account-address-x')
const accountBalanceEl = document.getElementById('account-balance')
const accountReserveEl = document.getElementById('account-reserve')
window.electronAPI.onUpdateAccountData((_event, value) => {
accountAddressClassicEl.innerText = value.classicAddress
accountAddressXEl.innerText = value.xAddress
accountBalanceEl.innerText = value.xrpBalance
accountReserveEl.innerText = value.xrpReserve
})
const txTableBodyEl = document.getElementById('tx-table').tBodies[0]
window.electronAPI.onUpdateTransactionData((_event, transactions) => {
for (let transaction of transactions) {
txTableBodyEl.insertAdjacentHTML( 'beforeend',
"<tr>" +
"<td>" + transaction.confirmed + "</td>" +
"<td>" + transaction.type + "</td>" +
"<td>" + transaction.from + "</td>" +
"<td>" + transaction.to + "</td>" +
"<td>" + transaction.value + "</td>" +
"<td>" + transaction.hash + "</td>" +
"</tr>"
)
}
})
const modalButton = document.getElementById('send-xrp-modal-button')
const modalDialog = new bootstrap.Modal(document.getElementById('send-xrp-modal'))
modalButton.addEventListener('click', () => {
modalDialog.show()
})
// Step 8 code additions - start
const accountVerificationEl = document.querySelector('.accountVerificationIndicator span')
// Step 8 code additions - end
const destinationAddressEl = document.getElementById('input-destination-address')
const destinationTagEl = document.getElementById('input-destination-tag')
const amountEl = document.getElementById('input-xrp-amount')
const sendXrpButtonEl = document.getElementById('send-xrp-submit-button')
// Step 8 code additions - start
destinationAddressEl.addEventListener('input', (event) => {
window.electronAPI.onDestinationAccountChange(destinationAddressEl.value)
})
window.electronAPI.onUpdateDomainVerificationData((_event, result) => {
accountVerificationEl.textContent = `Domain: ${result.domain || 'n/a'} Verified: ${result.verified}`
})
// Step 8 code additions - end
sendXrpButtonEl.addEventListener('click', () => {
modalDialog.hide()
const destinationAddress = destinationAddressEl.value
const destinationTag = destinationTagEl.value
const amount = amountEl.value
window.electronAPI.onClickSendXrp({destinationAddress, destinationTag, amount})
})
window.electronAPI.onSendXrpTransactionFinish((_event, result) => {
alert('Result: ' + result.result.meta.TransactionResult)
destinationAddressEl.value = ''
destinationTagEl.value = ''
amountEl.value = ''
})