Created
September 23, 2023 04:42
-
-
Save QuasarChains/d9dd7a4c256487f02fd3615cef9ef496 to your computer and use it in GitHub Desktop.
GC POAP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Gamechanger Attendance NFT</title> | |
<link rel="stylesheet" href="index.css" /> | |
<link rel="icon" type="image/x-icon" href="./favicon.ico"> | |
<script type="text/javascript" src="https://unpkg.com/json-url@2.3.1/dist/browser/json-url.js"></script> | |
<script src="https://cdn.jsdelivr.net/gh/ethereumjs/browser-builds/dist/ethereumjs-tx/ethereumjs-tx-1.3.3.min.js"></script> | |
</head> | |
<body> | |
<div class="flex-container"> | |
<div> | |
<h1>Gamechanger - Cardano over coffee</h1> | |
<h2>Proof of attendance NFT</h2> | |
<div id='nft-svg'><svg viewBox="0 0 800 400"> | |
<path id="bg" d="M 0 0 H 800 V 400 H 0 Z" fill='url("#bgG")' stroke="none"/> | |
<path id="NFT" d="M 20 50 C 40 40, 40 20, 650 60" fill="none" stroke-width="15" stroke='url("#NFTG")' stroke-linecap="round"></path> | |
<defs><linearGradient id="NFTG"><stop id="NFTg0" stop-color="hsl(276, 100%, 50%)" offset="0"></stop> | |
<stop id="NFTg1" stop-color="hsl(247, 100%, 50%)" offset="1"></stop></linearGradient> | |
<linearGradient id="bgG"><stop id="BGg0" stop-color="hsl(247, 100%, 50%)" offset="0"></stop> | |
<stop id="BGg1" stop-color="hsl(276, 100%, 50%)" offset="1"></stop></linearGradient></defs> | |
<path fill="none" stroke="#000000" stroke-width="20" stroke-dasharray="none" stroke-opacity="1" d="m 385, 162 h -169 v 75 h 159 V 200 H 270"/> | |
<path fill="none" stroke="#000000" stroke-width="20" stroke-dasharray="none" stroke-opacity="1" d="M 593,162 h -169 v 75 h 169"/> | |
</svg></div> | |
<h2 class="donation">Make a donation to the team. Move the slider</h2> | |
<div class="slidecontainer"> | |
<input type="range" min="1" max="1000" value="3" class="slider" id="myRange" | |
oninput="dragRange(this.value)"> | |
<input type="text" id="amountInput" class="amountInput" value="3" onchange="changeAmount(this.value)"> | |
<div id="denomination" class="denomination">ADA</div> | |
</div> | |
<button class="button" onclick="MakeGcScript()">Generate NFT transaction link</button> | |
<div id="linkDiv" class="link"><a id="poapLink" target=”_blank” href="https://gamechanger.finance/">Click this link to start the transaction</a></div> | |
<h3>Checkout the code and experiment</h3> | |
<a target=”_blank” href="https://codepen.io/M2tec/pen/LYggbRq">M2tec dApp codepen</a></div> | |
</div> | |
</div> | |
<script src="./index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function formatPoints(points, close) { | |
points = [...points]; | |
if (!Array.isArray(points[0])) { | |
points = points.map(({ x, y }) => [x, y]); | |
} | |
if (close) { | |
const lastPoint = points[points.length - 1]; | |
const secondToLastPoint = points[points.length - 2]; | |
const firstPoint = points[0]; | |
const secondPoint = points[1]; | |
points.unshift(lastPoint); | |
points.unshift(secondToLastPoint); | |
points.push(firstPoint); | |
points.push(secondPoint); | |
//console.log(points) | |
} | |
return points.flat(); | |
} | |
function spline(points = [], tension = 1, close = false, cb) { | |
points = formatPoints(points, close); | |
const size = points.length; | |
const last = size - 4; | |
const startPointX = close ? points[2] : points[0]; | |
const startPointY = close ? points[3] : points[1]; | |
let path = "M" + [startPointX, startPointY]; | |
cb && cb("MOVE", [startPointX, startPointY]); | |
const startIteration = close ? 2 : 0; | |
const maxIteration = close ? size - 4 : size - 2; | |
const inc = 2; | |
for (let i = startIteration; i < maxIteration; i += inc) { | |
const x0 = i ? points[i - 2] : points[0]; | |
const y0 = i ? points[i - 1] : points[1]; | |
const x1 = points[i + 0]; | |
const y1 = points[i + 1]; | |
const x2 = points[i + 2]; | |
const y2 = points[i + 3]; | |
const x3 = i !== last ? points[i + 4] : x2; | |
const y3 = i !== last ? points[i + 5] : y2; | |
const cp1x = x1 + ((x2 - x0) / 6) * tension; | |
const cp1y = y1 + ((y2 - y0) / 6) * tension; | |
const cp2x = x2 - ((x3 - x1) / 6) * tension; | |
const cp2y = y2 - ((y3 - y1) / 6) * tension; | |
path += "C" + [cp1x, cp1y, cp2x, cp2y, x2, y2]; | |
cb && cb("CURVE", [cp1x, cp1y, cp2x, cp2y, x2, y2]); | |
} | |
return path; | |
} | |
function generateRandomIntegerInRange(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function generatePoints(amount) { | |
points = [] | |
yscale = 45 + 345 * ( parseInt(amount)/1000) | |
for (var i=1;i<=6; i++) { | |
x1 = generateRandomIntegerInRange(10, 790) | |
y1 = 400 - generateRandomIntegerInRange(20, yscale) | |
point = [x1, y1] | |
points.push(point) | |
} | |
return points | |
} | |
function makeShape() { | |
let newAmount = document.getElementById('amountInput').value; | |
z = generatePoints(newAmount) | |
const path = spline(z, 1, false) | |
const nftPath = document.getElementById("NFT"); | |
nftPath.attributes.d.value = path | |
updateGradient(newAmount) | |
} | |
makeShape(); | |
function updateGradient(newAmount) { | |
// Line color | |
scaleValue = 50 + 50 * newAmount/1000 | |
color_purple = "hsl(276," + scaleValue + "%,60%)" | |
scaleValue = 50 + 50 * newAmount/1000 | |
color_blue = "hsl(243," + scaleValue + "%,60%)" | |
const bgGradient0 = document.getElementById("NFTg0"); | |
bgGradient0.style.stopColor = color_purple; | |
const bgGradient1 = document.getElementById("NFTg1"); | |
bgGradient1.style.stopColor = color_blue; | |
// Background color | |
scaleValue = 20 + 80 * newAmount/1000 | |
color_purple = "hsl(276," + scaleValue + "%,50%)" | |
scaleValue = 20 + 80 * newAmount/1000 | |
color_blue = "hsl(243," + scaleValue + "%,50%)" | |
const bgGradient2 = document.getElementById("BGg0"); | |
bgGradient2.style.stopColor = color_blue; | |
const bgGradient3 = document.getElementById("BGg1"); | |
bgGradient3.style.stopColor = color_purple; | |
} | |
function dragRange(newVal) { | |
let amountField = document.getElementById('amountInput'); | |
amountField.value = newVal; | |
makeShape() | |
} | |
function changeAmount(newVal) { | |
let myRange = document.getElementById('myRange'); | |
myRange.value = newVal; | |
makeShape() | |
} | |
//auxiliar function: Splits a buffer into a list of buffers | |
function bufferIntoBufferChunks(data, max){ | |
if(max <= 0) throw new Error('cannot split into zero (or smaller) length buffers') | |
if(data.length <= max) | |
return [data] | |
var out = [], len = 0 | |
while(len < data.length) { | |
out.push(data.slice(len, Math.min(len + max, data.length))) | |
len += max | |
} | |
return out | |
} | |
//Auxiliar function. Works with unicode chars, can be tested against LoremIpsumTransactum demo | |
function str2ArrayOfStr(str, size) { | |
if(!str) | |
return []; | |
const chunks = bufferIntoBufferChunks(ethereumjs.Buffer.Buffer.from(str),size).map(buffer=>buffer?.toString()); | |
return chunks; | |
} | |
//Turns a string into a "metadata string" | |
function str2metadataStr(str, size=64) { | |
if(!str) | |
return ""; | |
const chunks=str2ArrayOfStr(str,size); | |
if(chunks.length===1) | |
return chunks[0] | |
else | |
return chunks | |
} | |
//Turns a "metadata string" into the former string | |
function metadataStr2Str(strOrArray) { | |
if(!strOrArray) | |
return "" | |
if (Array.isArray(strOrArray)) | |
return strOrArray.join(""); | |
else | |
return strOrArray; | |
} | |
function MakeGcScript() { | |
const nftSvg = document.getElementById("nft-svg").innerHTML; | |
base64Svg = btoa(nftSvg) | |
splitSvg = str2metadataStr("data:image/svg+xml;base64," + base64Svg) | |
//console.log(splitSvg) | |
const link = document.getElementById("poapLink"); | |
const code = { | |
"type": "tx", | |
"ttl": 86400, | |
"title": "Proof of Attendance GC - Cardano over coffee", | |
"description": "", | |
"outputs": { | |
"addr_test1qzwg9p0zw6au40nwls803mx9lfeaxjfxy9p6el25r3nctjnp6ydulqht6r9z4ld0jms3a3c7gw45u32vhc2ftdp2f6rq57a9g2": [ | |
{ | |
"quantity": "2000000", | |
"policyId": "ada", | |
"assetName": "ada" | |
} | |
] | |
}, | |
"mints": [ | |
{ | |
"script": { | |
"issuers": [ | |
{ | |
"accountIndex": 0, | |
"addressIndex": 0 | |
} | |
], | |
"beforeSlotOffset": 90000 | |
}, | |
"assets": [ | |
{ | |
"assetName": "GC-POAP-COFFEE", | |
"quantity": "1" | |
} | |
] | |
} | |
], | |
"metadata": { | |
"721": { | |
"0": { | |
"GC-POAP-COFFEE": { | |
"author": "GC", | |
"name": "GC-POAP", | |
"image": "data:image/svg+xml;base64", | |
"mediaType": "image/svg+xml", | |
} | |
} | |
} | |
} | |
} | |
let amountRange = document.getElementById('myRange'); | |
lovelace_donation = parseInt(amountRange.value) * 1000000 | |
//console.log(lovelace_donation) | |
address = Object.keys(code.outputs)[0] | |
code.outputs[address][0]["quantity"] = lovelace_donation | |
code.metadata['721']['0']['GC-POAP-COFFEE']['image'] = splitSvg | |
//console.log(code) | |
//console.log(code.metadata['721']['0']['GC-POAP-COFFEE']) | |
//console.log(code.outputs) | |
const lib = JsonUrl('lzw'); // JsonUrl is added to the window | |
//generates the URL that is packed with the script | |
lib.compress(code) | |
.then(gcscript => { | |
link.href = "https://preprod-wallet.gamechanger.finance/api/1/tx/" + gcscript; | |
}) | |
.catch(err => { | |
link.innerHTML = "Error: " + err.message; | |
}); | |
const linkDiv = document.getElementById("linkDiv") | |
linkDiv.style.visibility = 'visible' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
background-color: #191c24; | |
font-family: Arial, Helvetica, sans-serif; | |
height: 100%; | |
color:#f9f9f9; | |
} | |
h1 { | |
display: flex; | |
justify-content: center; | |
margin-top: 50px; | |
margin-bottom: 5px; | |
} | |
h2 { | |
display: flex; | |
justify-content: center; | |
margin-top:10px; | |
margin-bottom: 40px; | |
} | |
.donation { | |
margin-top:80px; | |
} | |
input[type=text] { | |
padding: 12px 20px; | |
margin: 0 10px; | |
border-radius: 5px; | |
border: 2px solid #000000; | |
background-color: #6c7293; | |
color:#f9f9f9; | |
font-size: large; | |
font-weight: bold; | |
} | |
.button { | |
background-color: #191c24; | |
color: #6c7293; | |
border: 2px solid #6c7293; | |
width: 800px; | |
height: 100px; | |
font-size: 25px; | |
font-weight: bold; | |
border-radius: 3px; | |
} | |
a { | |
color: white; | |
font-size: 30px; | |
} | |
.link { | |
padding: 50px; | |
visibility: hidden; | |
display: flex; | |
justify-content: center; | |
} | |
.button:hover { | |
background-color: #0f1015; /* Green */ | |
color: white; | |
} | |
.flex-container { | |
display: flex; | |
justify-content:center; | |
width: 100%; | |
} | |
.slider { | |
width: 100%; | |
} | |
.slidecontainer { | |
margin-top: 30px; | |
margin-bottom: 30px; | |
display: flex; | |
} | |
.amountInput { | |
width: 100px; | |
text-align: right; | |
margin-left: 30px; | |
} | |
.denomination { | |
width: 70px; | |
display:flex; | |
justify-content: center; | |
align-items: center; | |
font-weight: bold; | |
color: white; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment