j"19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAutM$U<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>SymRe - URL shortening on Bitcoin</title>
<meta property="og:type" content="website">
<meta property="og:site_name" content="SymRe">
<meta name="twitter:creator" content="@torusJKL">
<meta property="og:title" content="SymRe - ShortURL on Bitcoin">
<meta name="twitter:title" content="SymRe - ShortURL on Bitcoin">
<meta property="og:description" content="SymRe allows to use Bitcoin to store and retrieve short URLs.">
<meta name="description" content="SymRe allows to use Bitcoin to store and retrieve short URLs.">
<meta name="twitter:description" content="SymRe allows to use Bitcoin to store and retrieve short URLs.">
<link rel="icon" type="image/png" href="https://static.bitcoinfiles.org/1529b27b9f33b8631230cfe6534e1ee4594b4f8130509b3e9a0ecf5f5320a0ee">
<script
type="text/javascript"
src="https://unpkg.com/[email protected]/bsv.min.js"
integrity="sha256-Hi6bj03v/dd33MN2P9MdeCYvAb+XPrrtoiGGmCKtU1Q="
crossorigin="anonymous"></script>
<script
type="text/javascript"
src="https://unpkg.com/[email protected]/bsv-message.min.js"
integrity="sha256-Z+xEqd6r+/wGDGCeuIR9tTuvwG/+4jUrXvp5crGioYs="
crossorigin="anonymous"></script>
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js"
integrity="sha256-25ncr0CpJhgbzkUiR3wu/Fkk9sSykRG2qX+upHfJUos="
crossorigin="anonymous"></script>
<script
type="text/javascript"
src="https://www.moneybutton.com/moneybutton.js"></script>
<script
type="text/javascript"
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<script
src="https://unpkg.com/[email protected]/dist/clipboard.min.js"
integrity="sha256-FiZwavyI2V6+EXO1U+xzLG3IKldpiTFf3153ea9zikQ="
crossorigin="anonymous"></script>
</head>
<style>
html {
font-size: 20px;
}
body {
color: #455A64;
background-color: #e2e2e2;
font-family: Helvetica, Arial, Sans-Serif;
}
iframe {
display:block;
}
a:link {
color:inherit;
}
a:visited {
color:inherit;
}
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas:
"title_logo"
"description"
"URLinput"
"error"
"moneybutton"
"result"
"advanced"
"haip-error"
"donate";
grid-gap: 5px;
}
.title_logo {
grid-area: title_logo;
justify-self: center;
margin-top: 10px;
}
.description {
grid-area: description;
justify-self: center;
}
.URLinput {
grid-area: URLinput;
justify-self: center;
}
.advanced {
grid-area: advanced;
justify-self: center;
}
.error {
grid-area: error;
justify-self: center;
color: red;
}
.haip-error {
grid-area: haip-error;
justify-self: center;
color: red;
}
.moneybutton {
grid-area: moneybutton;
justify-self: center;
}
.result {
grid-area: result;
justify-self: center;
background: #c5e0ff;
border: none;
border-radius: 0.4rem;
padding: 10px;
}
.donate {
grid-area: donate;
justify-self: center;
}
.input-text {
display: block;
margin: 0;
color: inherit;
width: 90%;
font-family: inherit;
font-weight: inherit;
border: none;
border-radius: 0.4rem;
padding: 10px;
font-size: 2.1rem;
width: 100%;
}
input::placeholder {
color: #455A64;
}
.button {
background: #1f4287;
border-radius: 8px;
font-family: Arial;
color: #ffffff;
font-size: 15px;
padding: 10px 20px 10px 20px;
text-decoration: none;
justify-items: center;
}
.button:hover {
background: #3cb0fd;
text-decoration: none;
}
.centered{
text-align:center;
}
.map-fields input {
font-size: 15px;
margin: 0.15rem .15rem;
min-width: 20%;
border: 1px solid #1f4287;
border-radius: 5px;
transition: border-color .5s ease-out;
text-align: center
}
.haip-fields input {
font-size: 15px;
margin: 0.15rem .15rem;
min-width: 35%;
border: 1px solid #1f4287;
border-radius: 5px;
transition: border-color .5s ease-out;
text-align: center
}
.haip-fields input:invalid {
border-left-color: salmon;
}
.svg-inline {
width: .875em;
}
.copyButton {
color: #555;
text-align: center;
padding: 3px;
border-radius: 3px;
width: 0.75em;
}
.copyButton:active {
color: #fff;
background-color: #1f4287;
}
</style>
<body onload="init();">
<div class="container">
<div class="title_logo">
<img src="https://static.bitcoinfiles.org/ca25febe75cc8fa450df355c149fe57aa5ba5645f15d32a56012d6b525935f3f">
</div>
<div class="description">
<h2>Create a short URL</h2>
<center><a href="https://github.com/torusJKL/SymRe/blob/master/documentation/README.md" target="_blank">Documentation</a></center>
</div>
<div class="URLinput">
<input type="text" id="urlInput" class="input-text" placeholder="Enter the address here" oninput="updateUrlButton()">
</div>
<div class="centered">
<button class="button" id="button-advanced" onclick="toggleAdvanced()">Show advanced options</button>
</div>
<div class="advanced">
<div class="centered map-fields" id="map-fields" style="display: none">
<input type="text" id="titleInput" placeholder="Title" oninput="updateMAP()"/>
<input type="text" id="descriptionInput" placeholder="Description" oninput="updateMAP()"/>
<input type="text" id="categoryInput" placeholder="Category" oninput="updateMAP()"/>
<input type="text" id="tagsInput" placeholder="Tags" oninput="updateMAP()"/>
</div>
<div class="centered haip-fields" id="haip-fields" style="display: none">
<input type="text" id="addressInput" placeholder="Persona / Bitcoin Address" oninput="updateHAIP()"/>
<input type="text" id="signatureInput" placeholder="Signature" oninput="updateHAIP()"/>
<br/>
<div>
<span id="haipHash"></span>
<svg id="copyText" class="btn svg-inline copyButton" aria-hidden="true" data-prefix="fas" data-icon="copy" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg="" style="display: none">
<path fill="currentColor" d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"></path>
</svg>
</div>
</div>
</div>
<div class="haip-error">
<div id="haip-error" style="display: none">The address or signature is not valid.</div>
</div>
<div class="moneybutton" id="button-URL"></div>
<div class="error">
<div id="error" style="display: none">The URL is not valid. It needs a protocol prefix (e.g. http:// or bit://) and text afterwards</div>
</div>
<div class="result">
<div id="bsv"></div>
<div id="legacy"></div>
<div id="tx"></div>
</div>
<div class="donate">
<h3>Donate</h3>
<div id="qr">
<canvas height="100" width="100"></canvas>
<div class="addr">1SymRe7erxM46GByucUWnB9fEEMgo7spd</div>
</div>
<div id="button-donation"></div>
</div>
</div>
</body>
<script type="text/javascript">
let oldURL = ''
let addr = "1SymRe7erxM46GByucUWnB9fEEMgo7spd"
let advancedActive = true
let elementsObj = null
let qr = new QRious({
element: document.querySelector('#qr canvas'),
value: 'bitcoin:' + addr
})
function init(){
toggleAdvanced()
updateUrlButton()
donationButton()
var clipboard = new ClipboardJS('.btn')
clipboard.on('success', function(e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);
e.clearSelection();
})
clipboard.on('error', function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
})
}
function toggleAdvanced(){
let button = document.getElementById("button-advanced")
let mapFields = document.getElementById("map-fields")
let haipFields = document.getElementById("haip-fields")
if (!advancedActive){
advancedActive = !advancedActive
mapFields.style.display = "block"
haipFields.style.display = "block"
button.innerHTML = "Hide advanced options"
return
}
if (advancedActive){
advancedActive = !advancedActive
mapFields.style.display = "none"
haipFields.style.display = "none"
button.innerHTML = "Show advanced options"
return
}
}
function updateUrlButton(){
let errorelem = document.getElementById('error')
let mbelem = document.getElementById('button-URL')
let resultelem = document.getElementsByClassName('result')
let myURL = document.querySelector('#urlInput').value.trim()
resultelem[0].style.display = "none"
if(myURL == ""){
mbelem.style.display = "none"
errorelem.style.display = "none"
return
}
if (myURL == oldURL)
return
if (!myURL == "" && !/(?:.+):\/\/(?:.+)/.test(myURL)){
errorelem.style.display = "block"
mbelem.style.display = "none"
oldURL = ""
return
}
oldURL = myURL
errorelem.style.display = "none"
createElemenstObj()
}
function updateMAP(){
let myURL = document.querySelector('#urlInput').value.trim()
if (elementsObj == null)
return
if (!myURL == "" && !/(?:.+):\/\/(?:.+)/.test(myURL))
return
let titleInput = document.getElementById('titleInput').value.trim()
let descriptionInput = document.getElementById('descriptionInput').value.trim()
let categoryInput = document.getElementById('categoryInput').value.trim()
let tagsInput = document.getElementById('tagsInput').value.trim()
if (titleInput || descriptionInput || categoryInput || tagsInput){
// this a temporary solution to force writting of these fiels
if (titleInput.length == 0)
titleInput = bsv.deps.Buffer.from('00', 'hex').toString()
if (descriptionInput.length == 0)
descriptionInput = bsv.deps.Buffer.from('00', 'hex').toString()
if (categoryInput.length == 0)
categoryInput = bsv.deps.Buffer.from('00', 'hex').toString()
if (tagsInput.length == 0)
tagsInput = bsv.deps.Buffer.from('00', 'hex').toString()
elementsObj.key3 = "|"
elementsObj.key4 = "1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5"
elementsObj.key5 = "SET"
elementsObj.key6 = "app"
elementsObj.key7 = "symre"
elementsObj.key8 = "title"
elementsObj.key9 = titleInput
elementsObj.key10 = "description"
elementsObj.key11 = descriptionInput
elementsObj.key12 = "category"
elementsObj.key13 = categoryInput
elementsObj.key14 = "tags"
elementsObj.key15 = tagsInput
updateHash()
updateHAIP()
updateScript()
return
}
deleteMapElements()
deleteHaipElements()
updateScript()
let haipHash = document.getElementById('haipHash')
haipHash.innerHTML = ""
let copyButton = document.getElementById("copyText")
copyButton.style.display = "none"
}
function updateHAIP(){
let address = document.getElementById('addressInput').value.trim()
let signature = document.getElementById('signatureInput').value.trim()
let haipHash = document.getElementById('haipHash').innerHTML
let errorelem = document.getElementById('haip-error')
let myURL = document.querySelector('#urlInput').value.trim()
if (!address || !signature || !haipHash)
return
if (!isBitcoinAddress(address)){
deleteHaipElements()
errorelem.style.display = "block"
return
}
if (!isSignatureValid(haipHash, address, signature)){
deleteHaipElements()
errorelem.style.display = "block"
return
}
errorelem.style.display = "none"
if (elementsObj == null)
return
if (!myURL == "" && !/(?:.+):\/\/(?:.+)/.test(myURL))
return
elementsObj.key16 = "|"
elementsObj.key17 = "1HA1P2exomAwCUycZHr8WeyFoy5vuQASE3"
elementsObj.key18 = "SHA256"
elementsObj.key19 = "BITCOIN_ECDSA"
elementsObj.key20 = address
elementsObj.key21 = signature
elementsObj.key22 = bsv.deps.Buffer.from('00', 'hex').toString()
updateScript()
}
function deleteMapElements(){
delete elementsObj.key3
delete elementsObj.key4
delete elementsObj.key5
delete elementsObj.key6
delete elementsObj.key7
delete elementsObj.key8
delete elementsObj.key9
delete elementsObj.key10
delete elementsObj.key11
delete elementsObj.key12
delete elementsObj.key13
delete elementsObj.key14
delete elementsObj.key15
}
function deleteHaipElements(){
delete elementsObj.key16
delete elementsObj.key17
delete elementsObj.key18
delete elementsObj.key19
delete elementsObj.key20
delete elementsObj.key21
delete elementsObj.key22
}
function isBitcoinAddress(address){
return bsv.Address.isValid(address)
}
function isSignatureValid(messageHash, address, signature){
var verify = bsvMessage.verify(messageHash, address, signature)
return verify
}
function updateScript(){
let asmScript = createOpReturn(elementsObj)
console.log("ASM script: \"" + asmScript + "\"")
urlButton(asmScript)
}
function updateHash(){
let hashObj = clone(elementsObj)
let key = "key" + hashObj.lengh
hashObj[key] = "|"
let scriptArr = objToArray(hashObj)
let hexScript = bsv.Script.buildDataOut(scriptArr).toHex()
console.log("script for hash: " + hexScript)
let hash = bsv.crypto.Hash.sha256(bsv.deps.Buffer.from(hexScript)).toString('hex')
console.log("hash: " + hash)
let haipHash = document.getElementById('haipHash')
haipHash.innerHTML = hash
let copyButton = document.getElementById("copyText")
copyButton.style.display = "inline"
copyButton.setAttribute("data-clipboard-text", hash)
}
function createElemenstObj(){
urlInput = document.querySelector('#urlInput').value.trim()
elementsObj = {key1:"1SymRe7erxM46GByucUWnB9fEEMgo7spd", key2:urlInput}
updateMAP()
}
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
function createOpReturn(elementsObj){
let scriptArr = objToArray(elementsObj)
let script = bsv.Script.buildDataOut(scriptArr).toASM()
return script
}
function objToArray(obj){
var array = $.map(obj, function(value, index) { return [value]; });
return array
}
function stringToHex(str) {
var hexStr = bsv.deps.Buffer.from(str).toString('hex')
return hexStr
}
function toOpReturnASM(myURL){
return "OP_RETURN " + stringToHex('1SymRe7erxM46GByucUWnB9fEEMgo7spd') + " " + stringToHex(myURL)
}
function getShortURL(txid, length){
return bsv.encoding.Base58.fromHex(txid.substring(0,length)).toString()
}
function urlButton(OpReturnASM){
var elem = document.getElementById('button-URL')
elem.style.display = "block"
moneyButton.render(elem, {
outputs: [{
amount: "0",
currency: "USD",
type: 'SCRIPT',
script: OpReturnASM
},
{
to: "1SymRe7erxM46GByucUWnB9fEEMgo7spd",
amount: "0.00001004",
currency: "BSV",
}],
clientIdentifier: "3a2633a21e8edf7bdcec5568ace866ff",
onPayment: function (r) {
console.log('success:', r)
let resultelem = document.getElementsByClassName('result')
resultelem[0].style.display = "block"
let shortURL = getShortURL(r.txid, 10)
document.querySelector("#bsv").innerHTML = "<a href='https://bottle.bitdb.network/'>Bottle</a>: <a target='_blank' href='bit://1SymRe7erxM46GByucUWnB9fEEMgo7spd/" + shortURL + "'>bit://1SymRe7erxM46GByucUWnB9fEEMgo7spd/" + shortURL + "</a><br/>"
document.querySelector("#legacy").innerHTML = "Legacy: <a target='_blank' href='https://sym.re/" + shortURL + "'>https://sym.re/" + shortURL + "</a><br/>"
document.querySelector("#tx").innerHTML = "tx: <a target='_blank' href='https://whatsonchain.com/tx/" + r.txid + "'>" + r.txid + "</a>"
},
onError: function (r) {
console.log('error:', r)
let resultelem = document.getElementsByClassName('result')
resultelem[0].style.display = "block"
document.querySelector("#tx").innerHTML = "An error occured: " + r
}
})
}
function donationButton(){
var elem = document.getElementById('button-donation')
moneyButton.render(elem, {
amount: "0.0001",
currency: "BSV",
editable: true,
label: "Donate",
to: "1SymRe7erxM46GByucUWnB9fEEMgo7spd",
type: "tip"
})
}
</script>
</html>
text/html; charset=utf-8UTF-8SymRe_create.html
https://whatsonchain.com/tx/fd6ad92a8465e2a1208379edb7f805f09bd67207c82597a994274a7890f30721