mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-02-01 03:12:15 +00:00
ZcashClient.sync()
Currently synchronous, but that's fine for a demo.
This commit is contained in:
parent
c9ad643653
commit
b4252fa9d3
21
README.md
21
README.md
@ -12,7 +12,26 @@
|
||||
$ ./build.sh
|
||||
```
|
||||
|
||||
## Running
|
||||
## Running the backend
|
||||
|
||||
Web browsers currently cannot talk directly to gRPC servers, so it is necessary to run a
|
||||
proxy as part of the backend. The `envoy/` subdirectory contains a Dockerfile and config
|
||||
file for an Envoy proxy that listens on `localhost:8081` and will route requests to a
|
||||
`lightwalletd` frontend listening on `localhost:9067`.
|
||||
|
||||
See [the `lightwalletd` documentation](https://github.com/zcash-hackworks/lightwalletd)
|
||||
for details on how to set up a local `lightwalletd` testnet instance. Note that when
|
||||
starting the frontend, you may need to use `--bind-addr 0.0.0.0:9067` so that the Docker
|
||||
container can access it.
|
||||
|
||||
To build and run the Envoy proxy:
|
||||
|
||||
```sh
|
||||
$ docker build -t lightwalletd/envoy -f envoy/envoy.Dockerfile envoy
|
||||
$ docker run -d -p 8081:8081 --network=host lightwalletd/envoy
|
||||
```
|
||||
|
||||
## Running the demo
|
||||
|
||||
```sh
|
||||
$ cd demo-www
|
||||
|
@ -15,6 +15,7 @@
|
||||
<p>That's your Zcash address!</p>
|
||||
<h2 id="zcash-client-balance"></h2>
|
||||
<p id="zcash-client-no-balance">You have no TAZ. Go <a href="https://faucet.testnet.z.cash/" target="blank">here</a> to get some!</p>
|
||||
<p id="zcash-client-sync-status">Syncing...</p>
|
||||
</div>
|
||||
<script src="./bootstrap.js"></script>
|
||||
</body>
|
||||
|
@ -3,8 +3,9 @@ import { ZcashClient } from 'zcash-client-sdk'
|
||||
const address = document.getElementById('zcash-client-address')
|
||||
const balance = document.getElementById('zcash-client-balance')
|
||||
const noBalance = document.getElementById('zcash-client-no-balance')
|
||||
const syncStatus = document.getElementById('zcash-client-sync-status')
|
||||
|
||||
var zcashClient = new ZcashClient({
|
||||
var zcashClient = new ZcashClient('http://localhost:8081', {
|
||||
setAddress: (newAddress) => {
|
||||
address.textContent = newAddress
|
||||
},
|
||||
@ -15,11 +16,24 @@ var zcashClient = new ZcashClient({
|
||||
} else {
|
||||
noBalance.style.display = ''
|
||||
}
|
||||
},
|
||||
updateSyncStatus: (syncedHeight, latestHeight) => {
|
||||
if (syncedHeight === latestHeight) {
|
||||
syncStatus.textContent = `Synced! Latest height: ${latestHeight}`
|
||||
} else {
|
||||
syncStatus.textContent = `Syncing (${syncedHeight} / ${latestHeight})...`
|
||||
}
|
||||
}
|
||||
}, {
|
||||
height: 500000,
|
||||
hash: '004fada8d4dbc5e80b13522d2c6bd0116113c9b7197f0c6be69bc7a62f2824cd',
|
||||
sapling_tree: '01b733e839b5f844287a6a491409a991ec70277f39a50c99163ed378d23a829a0700100001916db36dfb9a0cf26115ed050b264546c0fa23459433c31fd72f63d188202f2400011f5f4e3bd18da479f48d674dbab64454f6995b113fa21c9d8853a9e764fb3e1f01df9d2c233ca60360e3c2bb73caf5839a1be634c8b99aea22d02abda2e747d9100001970d41722c078288101acd0a75612acfb4c434f2a55aab09fb4e812accc2ba7301485150f0deac7774dcd0fe32043bde9ba2b6bbfff787ad074339af68e88ee70101601324f1421e00a43ef57f197faf385ee4cac65aab58048016ecbd94e022973701e1b17f4bd9d1b6ca1107f619ac6d27b53dd3350d5be09b08935923cbed97906c0000000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39'
|
||||
})
|
||||
|
||||
zcashClient.load(() => {
|
||||
// Loading complete, show the wallet
|
||||
document.getElementById('zcash-client-loading').remove()
|
||||
document.getElementById('zcash-client-content').style.display = ''
|
||||
|
||||
zcashClient.sync()
|
||||
})
|
||||
|
3
envoy/envoy.Dockerfile
Normal file
3
envoy/envoy.Dockerfile
Normal file
@ -0,0 +1,3 @@
|
||||
FROM envoyproxy/envoy:latest
|
||||
COPY ./envoy.yaml /etc/envoy/envoy.yaml
|
||||
CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml
|
45
envoy/envoy.yaml
Normal file
45
envoy/envoy.yaml
Normal file
@ -0,0 +1,45 @@
|
||||
admin:
|
||||
access_log_path: /tmp/admin_access.log
|
||||
address:
|
||||
socket_address: { address: 0.0.0.0, port_value: 9901 }
|
||||
|
||||
static_resources:
|
||||
listeners:
|
||||
- name: listener_0
|
||||
address:
|
||||
socket_address: { address: 0.0.0.0, port_value: 8081 }
|
||||
filter_chains:
|
||||
- filters:
|
||||
- name: envoy.http_connection_manager
|
||||
config:
|
||||
codec_type: auto
|
||||
stat_prefix: ingress_http
|
||||
route_config:
|
||||
name: local_route
|
||||
virtual_hosts:
|
||||
- name: local_service
|
||||
domains: ["*"]
|
||||
routes:
|
||||
- match: { prefix: "/" }
|
||||
route:
|
||||
cluster: lightwalletd_frontend
|
||||
max_grpc_timeout: 0s
|
||||
cors:
|
||||
allow_origin:
|
||||
- "*"
|
||||
allow_methods: GET, PUT, DELETE, POST, OPTIONS
|
||||
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
|
||||
max_age: "1728000"
|
||||
expose_headers: custom-header-1,grpc-status,grpc-message
|
||||
enabled: true
|
||||
http_filters:
|
||||
- name: envoy.grpc_web
|
||||
- name: envoy.cors
|
||||
- name: envoy.router
|
||||
clusters:
|
||||
- name: lightwalletd_frontend
|
||||
connect_timeout: 0.25s
|
||||
type: logical_dns
|
||||
http2_protocol_options: {}
|
||||
lb_policy: round_robin
|
||||
hosts: [{ socket_address: { address: localhost, port_value: 9067 }}]
|
@ -1,17 +1,114 @@
|
||||
import { Client } from 'zcash-client-backend-wasm'
|
||||
|
||||
const { BlockID, BlockRange, ChainSpec } = require('./service_pb.js')
|
||||
const { CompactTxStreamerClient } = require('./service_grpc_web_pb.js')
|
||||
const grpc = {}
|
||||
grpc.web = require('grpc-web')
|
||||
|
||||
const COIN = 100000000
|
||||
|
||||
const CHAIN_REFRESH_INTERVAL = 60 * 1000
|
||||
const BATCH_SIZE = 1000
|
||||
|
||||
export class ZcashClient {
|
||||
constructor (uiHandlers) {
|
||||
constructor (lightwalletdURL, uiHandlers, checkpoint) {
|
||||
this.lightwalletd = new CompactTxStreamerClient(lightwalletdURL)
|
||||
this.client = Client.new()
|
||||
this.uiHandlers = uiHandlers
|
||||
|
||||
if (!this.client.set_initial_block(checkpoint.height, checkpoint.hash, checkpoint.sapling_tree)) {
|
||||
console.error('Invalid checkpoint data')
|
||||
}
|
||||
}
|
||||
|
||||
updateUI () {
|
||||
this.uiHandlers.updateBalance(this.client.balance() / COIN)
|
||||
}
|
||||
|
||||
sync () {
|
||||
var self = this
|
||||
|
||||
var chainSpec = new ChainSpec()
|
||||
|
||||
self.lightwalletd.getLatestBlock(chainSpec, {}, (err, latestBlock) => {
|
||||
if (err) {
|
||||
console.error('Error fetching latest block')
|
||||
console.error(`Error code: ${err.code} "${err.message}"`)
|
||||
return
|
||||
}
|
||||
|
||||
var startHeight = self.client.last_scanned_height()
|
||||
var latestHeight = latestBlock.getHeight()
|
||||
if (startHeight === latestHeight) {
|
||||
console.log('No new blocks')
|
||||
window.setTimeout(() => { self.sync() }, CHAIN_REFRESH_INTERVAL)
|
||||
return
|
||||
}
|
||||
|
||||
var endHeight
|
||||
if (latestHeight - startHeight < BATCH_SIZE) {
|
||||
endHeight = latestHeight
|
||||
} else {
|
||||
endHeight = startHeight + BATCH_SIZE - 1
|
||||
}
|
||||
console.debug(`Latest block: ${latestHeight}`)
|
||||
console.debug(`Requesting blocks in range [${startHeight}, ${endHeight}]`)
|
||||
|
||||
var blockStart = new BlockID()
|
||||
blockStart.setHeight(startHeight)
|
||||
var blockEnd = new BlockID()
|
||||
blockEnd.setHeight(endHeight)
|
||||
var blockRange = new BlockRange()
|
||||
blockRange.setStart(blockStart)
|
||||
blockRange.setEnd(blockEnd)
|
||||
|
||||
var stream = self.lightwalletd.getBlockRange(blockRange, {})
|
||||
stream.on('data', (block) => {
|
||||
// Scan the block
|
||||
if (!self.client.scan_block(block.serializeBinary())) {
|
||||
console.error('Failed to scan block')
|
||||
}
|
||||
})
|
||||
stream.on('status', (status) => {
|
||||
if (status.metadata) {
|
||||
console.debug('Received metadata')
|
||||
console.debug(status.metadata)
|
||||
}
|
||||
if (status.code !== grpc.web.StatusCode.OK) {
|
||||
console.error(`Error code: ${status.code} "${status.details}"`)
|
||||
}
|
||||
|
||||
// Perform end-of-stream updates here, because we don't always get the
|
||||
// 'end' event for some reason, but we do always get the 'status' event.
|
||||
|
||||
var syncedHeight = self.client.last_scanned_height()
|
||||
if (endHeight !== syncedHeight) {
|
||||
console.error('Block stream finished before expected end height')
|
||||
}
|
||||
|
||||
// Update UI for current chain status
|
||||
console.log(`Scanned to height: ${syncedHeight}`)
|
||||
self.updateUI()
|
||||
self.uiHandlers.updateSyncStatus(syncedHeight, latestHeight)
|
||||
|
||||
// Queue up the next sync
|
||||
if (syncedHeight === latestHeight) {
|
||||
console.log('Finished syncing!')
|
||||
window.setTimeout(() => { self.sync() }, CHAIN_REFRESH_INTERVAL)
|
||||
} else {
|
||||
self.sync()
|
||||
}
|
||||
})
|
||||
stream.on('error', (err) => {
|
||||
console.error('Error while streaming blocks')
|
||||
console.error(`Error code: ${err.code} "${err.message}"`)
|
||||
})
|
||||
stream.on('end', () => {
|
||||
console.debug('Block stream end signal received')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
load (onFinished) {
|
||||
var self = this
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user