Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions cmd/dispenser/index.html.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<head>
<title>Algorand dispenser</title>
<script src='https://www.google.com/recaptcha/api.js'>
</script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous">
</script>
<script>
var ADDRESS_REGEX = /[A-Z0-9]{58}/

function sanitize(string) {
const entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
};
return String(string).replace(/[&<>"'`=\/]/g, function (s) {
return entityMap[s];
});
}

function loadparam() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const account = sanitize(urlParams.get('account'))

if (ADDRESS_REGEX.test(account)) {
$('#target').val(account);
}
}

function onload() {
loadparam();
$('#dispense').click(function(e) {
var recaptcha = grecaptcha.getResponse();
var target = sanitize($('#target').val());

if (ADDRESS_REGEX.test(target)) {
$('#status').html('Sending request..');
var req = $.post('/dispense', {
recaptcha: recaptcha,
target: target,
}, function(data) {
$('#status').text('Code ' + req.status + ' ' + req.statusText + ': ' + req.responseText);
}).fail(function() {
$('#status').text('Code ' + req.status + ' ' + req.statusText + ': ' + req.responseText);
});
}
else {
$('#status').text('Please enter a valid Algorand address')
}
});
}
</script>
</head>
<body onload="onload()">
<h1>Algorand dispenser</h1>
<div class="g-recaptcha" data-sitekey="{{.RecaptchaSiteKey}}">
</div>
<div>
<p>The dispensed Algos have no monetary value and should only be used to test applications.</p>
<p>This service is gracefully provided to enable development on the Algorand blockchain test networks.</p>
<p>Please do not abuse it by requesting more Algos than needed.</p>
</div>
<div>
<input id="target" placeholder="target address" size="80">
<button id="dispense">Dispense</button>
</div>
<div>
Status: <span id="status"></span>
</div>
</body>
</html>
62 changes: 6 additions & 56 deletions cmd/dispenser/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package main

import (
_ "embed"
"html"

// "bytes"
"encoding/json"
"flag"
Expand Down Expand Up @@ -63,61 +66,8 @@ type dispenserSiteConfig struct {
topPage string
}

const topPageTemplate = `
<html>
<head>
<title>Algorand dispenser</title>
<script src='https://www.google.com/recaptcha/api.js'>
</script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous">
</script>
<script>
function loadparam() {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
$('#target').val(urlParams.get('account'));
}

function onload() {
loadparam();
$('#dispense').click(function(e) {
var recaptcha = grecaptcha.getResponse();
var target = $('#target').val();

$('#status').html('Sending request..');
var req = $.post('/dispense', {
recaptcha: recaptcha,
target: target,
}, function(data) {
$('#status').html('Code ' + req.status + ' ' + req.statusText + ': ' + req.responseText);
}).fail(function() {
$('#status').html('Code ' + req.status + ' ' + req.statusText + ': ' + req.responseText);
});
});
}
</script>
</head>
<body onload="onload()">
<h1>Algorand dispenser</h1>
<div class="g-recaptcha" data-sitekey="{{.RecaptchaSiteKey}}">
</div>
<div>
<p>The dispensed Algos have no monetary value and should only be used to test applications.</p>
<p>This service is gracefully provided to enable development on the Algorand blockchain test networks.</p>
<p>Please do not abuse it by requesting more Algos than needed.</p>
</div>
<div>
<input id="target" placeholder="target address" size="80">
<button id="dispense">Dispense</button>
</div>
<div>
Status: <span id="status"></span>
</div>
</body>
</html>
`
//go:embed index.html.tpl
var topPageTemplate string

func getConfig(r *http.Request) dispenserSiteConfig {
return configMap[r.Host]
Expand Down Expand Up @@ -190,7 +140,7 @@ func dispense(w http.ResponseWriter, r *http.Request) {
return
}

target := targets[0]
target := html.EscapeString(targets[0])

c, ok := client[r.Host]
if !ok {
Expand Down