diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..d3b6bcb
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = 0
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f90e0b0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+
+.DS_Store
+node_modules
+
+package-lock.json
+
+#Hardhat files
+cache
+artifacts
+archives
diff --git a/docs/browserconfig.xml b/docs/browserconfig.xml
new file mode 100644
index 0000000..7f5d1e5
--- /dev/null
+++ b/docs/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #ee141e
+
+
+
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..f6fc652
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/images/bg-gns-1.jpg b/docs/images/bg-gns-1.jpg
new file mode 100644
index 0000000..b2c2f29
Binary files /dev/null and b/docs/images/bg-gns-1.jpg differ
diff --git a/docs/images/bg-gns-2.jpg b/docs/images/bg-gns-2.jpg
new file mode 100644
index 0000000..a245701
Binary files /dev/null and b/docs/images/bg-gns-2.jpg differ
diff --git a/docs/images/bg-space.jpg b/docs/images/bg-space.jpg
new file mode 100644
index 0000000..2428c6a
Binary files /dev/null and b/docs/images/bg-space.jpg differ
diff --git a/docs/images/bg-space.png b/docs/images/bg-space.png
new file mode 100644
index 0000000..fa68995
Binary files /dev/null and b/docs/images/bg-space.png differ
diff --git a/docs/images/diagram-sidechain.png b/docs/images/diagram-sidechain.png
new file mode 100644
index 0000000..10a1c66
Binary files /dev/null and b/docs/images/diagram-sidechain.png differ
diff --git a/docs/images/gcoin.png b/docs/images/gcoin.png
new file mode 100644
index 0000000..7d43c34
Binary files /dev/null and b/docs/images/gcoin.png differ
diff --git a/docs/images/gryph-8bit-7.png b/docs/images/gryph-8bit-7.png
new file mode 100644
index 0000000..453db67
Binary files /dev/null and b/docs/images/gryph-8bit-7.png differ
diff --git a/docs/images/home-city.png b/docs/images/home-city.png
new file mode 100644
index 0000000..ec1c336
Binary files /dev/null and b/docs/images/home-city.png differ
diff --git a/docs/images/peg-3darvr.png b/docs/images/peg-3darvr.png
new file mode 100644
index 0000000..57e9848
Binary files /dev/null and b/docs/images/peg-3darvr.png differ
diff --git a/docs/images/peg-art.png b/docs/images/peg-art.png
new file mode 100644
index 0000000..53c8e1a
Binary files /dev/null and b/docs/images/peg-art.png differ
diff --git a/docs/images/peg-fashion.png b/docs/images/peg-fashion.png
new file mode 100644
index 0000000..fdd8f4c
Binary files /dev/null and b/docs/images/peg-fashion.png differ
diff --git a/docs/images/peg-games.png b/docs/images/peg-games.png
new file mode 100644
index 0000000..d9ca87d
Binary files /dev/null and b/docs/images/peg-games.png differ
diff --git a/docs/images/peg-land.png b/docs/images/peg-land.png
new file mode 100644
index 0000000..7eb0732
Binary files /dev/null and b/docs/images/peg-land.png differ
diff --git a/docs/images/peg-mobile.png b/docs/images/peg-mobile.png
new file mode 100644
index 0000000..81c602d
Binary files /dev/null and b/docs/images/peg-mobile.png differ
diff --git a/docs/images/peg-music.png b/docs/images/peg-music.png
new file mode 100644
index 0000000..e9205ac
Binary files /dev/null and b/docs/images/peg-music.png differ
diff --git a/docs/images/peg-sports.png b/docs/images/peg-sports.png
new file mode 100644
index 0000000..4fd6913
Binary files /dev/null and b/docs/images/peg-sports.png differ
diff --git a/docs/images/sprite-chains.png b/docs/images/sprite-chains.png
new file mode 100644
index 0000000..6f9ce6d
Binary files /dev/null and b/docs/images/sprite-chains.png differ
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..1f87b9d
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+ GRY.PH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Crosschain NFT Marketplace
+
+ Stake the Next Level of Digital
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Read the Whitepaper
+
+
+
+
+
+
+
+
The Next Utopia
+
GRYPH Chain
+
+ An ethereum-linked sidechain made specifically for the GRYPH Marketplace. Experience
+ fast and cheap gas costs when minting, listing and trading that scales.
+
+
The Economy Engine
+
+ GRYPH is powered by the world's first decentralized economy engine that
+ allows users to buy and sell provably asset backed $GRYPH direct.
+
+
Learn More
+
+
+
+
+
+
+
+
+
+
+
+
+
The NFT Wallet You Deserve
+
+ List, Buy, Send and Collect Digital Art
+ Discover NFTs Across All Blockchains
+ Zero Configuration NFT Detection
+ Your Wallet, Your Data
+
+
Coming Soon
+
+
+
+
+
+
GRY.PH Naming Service
+
Decentralized Naming for sellers, buyers and art collections.
+
+
+
+
+
+
+
Staking $GRYPH
+
+ Earn on Successful Listings & Purchases
+ Use on Platform Fees & Gas
+ HODL for Rewards & Exclusive Deals
+ Zero Fees for All NFTs Created on the Side Chain
+ Cheap Marketplace Gas Fees. Forever.
+
+
Get Whitelisted
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/scripts/collection.js b/docs/scripts/collection.js
new file mode 100644
index 0000000..909d152
--- /dev/null
+++ b/docs/scripts/collection.js
@@ -0,0 +1,34 @@
+(async() => {
+ const state = {}
+ const connected = async function(newstate) {
+ Object.assign(state, newstate, {
+ //account: '0xe4d48122f4e3cc276480dc28db9e023fd66e39e8'
+ })
+ blockapi.notify('success', 'Wallet connected')
+
+ document.getElementById('connected').classList.remove('hidden');
+ document.getElementById('disconnected').classList.add('hidden');
+
+ document.getElementById('wallet-address').innerHTML = [
+ newstate.account.substr(0, 6),
+ newstate.account.substr(newstate.account.length - 4)
+ ].join('...')
+ }
+
+ const disconnected = function(e) {
+ if (e?.message) {
+ blockapi.notify('error', e.message)
+ } else {
+ blockapi.notify('success', 'Wallet disconnected')
+ }
+
+ document.getElementById('disconnected').classList.remove('hidden');
+ document.getElementById('connected').classList.add('hidden');
+ }
+
+ window.doon('body')
+ window.addEventListener('disconnect-click', disconnected)
+ window.addEventListener('connect-click', async(e) => {
+ blockapi.connect(blockmetadata, connected, disconnected)
+ })
+})()
\ No newline at end of file
diff --git a/docs/scripts/contracts.js b/docs/scripts/contracts.js
new file mode 100644
index 0000000..495e512
--- /dev/null
+++ b/docs/scripts/contracts.js
@@ -0,0 +1,13 @@
+window.blockmetadata = {
+ "chain_id": 80001,
+ "chain_name": "Polygon (MATIC)",
+ "chain_scan": "https://rpc-mumbai.maticvigil.com/", //testnet
+ //"chain_scan": "https://bscscan.com/", //mainnet
+ "contracts": {
+ "collection": {
+ "address": "0x2D368564a298F6738049cbCDB25E689b6157dc35", //testnet
+ //"address": "0x2D368564a298F6738049cbCDB25E689b6157dc35", //mainnet
+ "abi": []
+ }
+ }
+}
diff --git a/docs/scripts/home.js b/docs/scripts/home.js
new file mode 100644
index 0000000..8089860
--- /dev/null
+++ b/docs/scripts/home.js
@@ -0,0 +1,13 @@
+(() => {
+ const carousel = Array.from(document.querySelectorAll('#carousel img'))
+ window.addEventListener('typewriter-next', (e) => {
+ console.log(e.index, e.text)
+ carousel.forEach((image, index) => {
+ if (e.index == index) {
+ image.classList.add('active')
+ } else {
+ image.classList.remove('active')
+ }
+ })
+ })
+})()
\ No newline at end of file
diff --git a/docs/scripts/home/particle.js b/docs/scripts/home/particle.js
new file mode 100644
index 0000000..325d834
--- /dev/null
+++ b/docs/scripts/home/particle.js
@@ -0,0 +1,1541 @@
+/* -----------------------------------------------
+/* Author : Vincent Garreau - vincentgarreau.com
+/* MIT license: http://opensource.org/licenses/MIT
+/* Demo / Generator : vincentgarreau.com/particles.js
+/* GitHub : github.com/VincentGarreau/particles.js
+/* How to use? : Check the GitHub README
+/* v2.0.0
+/* ----------------------------------------------- */
+
+var pJS = function(tag_id, params){
+
+ var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
+
+ /* particles.js variables with default values */
+ this.pJS = {
+ canvas: {
+ el: canvas_el,
+ w: canvas_el.offsetWidth,
+ h: canvas_el.offsetHeight
+ },
+ particles: {
+ number: {
+ value: 400,
+ density: {
+ enable: true,
+ value_area: 800
+ }
+ },
+ color: {
+ value: '#fff'
+ },
+ shape: {
+ type: 'circle',
+ stroke: {
+ width: 0,
+ color: '#ff0000'
+ },
+ polygon: {
+ nb_sides: 5
+ },
+ image: {
+ src: '',
+ width: 100,
+ height: 100
+ }
+ },
+ opacity: {
+ value: 1,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 2,
+ opacity_min: 0,
+ sync: false
+ }
+ },
+ size: {
+ value: 20,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 20,
+ size_min: 0,
+ sync: false
+ }
+ },
+ line_linked: {
+ enable: true,
+ distance: 100,
+ color: '#fff',
+ opacity: 1,
+ width: 1
+ },
+ move: {
+ enable: true,
+ speed: 2,
+ direction: 'none',
+ random: false,
+ straight: false,
+ out_mode: 'out',
+ bounce: false,
+ attract: {
+ enable: false,
+ rotateX: 3000,
+ rotateY: 3000
+ }
+ },
+ array: []
+ },
+ interactivity: {
+ detect_on: 'canvas',
+ events: {
+ onhover: {
+ enable: true,
+ mode: 'grab'
+ },
+ onclick: {
+ enable: true,
+ mode: 'push'
+ },
+ resize: true
+ },
+ modes: {
+ grab:{
+ distance: 100,
+ line_linked:{
+ opacity: 1
+ }
+ },
+ bubble:{
+ distance: 200,
+ size: 80,
+ duration: 0.4
+ },
+ repulse:{
+ distance: 200,
+ duration: 0.4
+ },
+ push:{
+ particles_nb: 4
+ },
+ remove:{
+ particles_nb: 2
+ }
+ },
+ mouse:{}
+ },
+ retina_detect: false,
+ fn: {
+ interact: {},
+ modes: {},
+ vendors:{}
+ },
+ tmp: {}
+ };
+
+ var pJS = this.pJS;
+
+ /* params settings */
+ if(params){
+ Object.deepExtend(pJS, params);
+ }
+
+ pJS.tmp.obj = {
+ size_value: pJS.particles.size.value,
+ size_anim_speed: pJS.particles.size.anim.speed,
+ move_speed: pJS.particles.move.speed,
+ line_linked_distance: pJS.particles.line_linked.distance,
+ line_linked_width: pJS.particles.line_linked.width,
+ mode_grab_distance: pJS.interactivity.modes.grab.distance,
+ mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
+ mode_bubble_size: pJS.interactivity.modes.bubble.size,
+ mode_repulse_distance: pJS.interactivity.modes.repulse.distance
+ };
+
+
+ pJS.fn.retinaInit = function(){
+
+ if(pJS.retina_detect && window.devicePixelRatio > 1){
+ pJS.canvas.pxratio = window.devicePixelRatio;
+ pJS.tmp.retina = true;
+ }
+ else{
+ pJS.canvas.pxratio = 1;
+ pJS.tmp.retina = false;
+ }
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
+
+ pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
+ pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
+ pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
+ pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
+ pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
+ pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
+
+ };
+
+
+
+ /* ---------- pJS functions - canvas ------------ */
+
+ pJS.fn.canvasInit = function(){
+ pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
+ };
+
+ pJS.fn.canvasSize = function(){
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ if(pJS && pJS.interactivity.events.resize){
+
+ window.addEventListener('resize', function(){
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight;
+
+ /* resize canvas */
+ if(pJS.tmp.retina){
+ pJS.canvas.w *= pJS.canvas.pxratio;
+ pJS.canvas.h *= pJS.canvas.pxratio;
+ }
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ /* repaint canvas on anim disabled */
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesEmpty();
+ pJS.fn.particlesCreate();
+ pJS.fn.particlesDraw();
+ pJS.fn.vendors.densityAutoParticles();
+ }
+
+ /* density particles enabled */
+ pJS.fn.vendors.densityAutoParticles();
+
+ });
+
+ }
+
+ };
+
+
+ pJS.fn.canvasPaint = function(){
+ pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+ pJS.fn.canvasClear = function(){
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+
+ /* --------- pJS functions - particles ----------- */
+
+ pJS.fn.particle = function(color, opacity, position){
+
+ /* size */
+ this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
+ if(pJS.particles.size.anim.enable){
+ this.size_status = false;
+ this.vs = pJS.particles.size.anim.speed / 100;
+ if(!pJS.particles.size.anim.sync){
+ this.vs = this.vs * Math.random();
+ }
+ }
+
+ /* position */
+ this.x = position ? position.x : Math.random() * pJS.canvas.w;
+ this.y = position ? position.y : Math.random() * pJS.canvas.h;
+
+ /* check position - into the canvas */
+ if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
+ else if(this.x < this.radius*2) this.x = this.x + this.radius;
+ if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
+ else if(this.y < this.radius*2) this.y = this.y + this.radius;
+
+ /* check position - avoid overlap */
+ if(pJS.particles.move.bounce){
+ pJS.fn.vendors.checkOverlap(this, position);
+ }
+
+ /* color */
+ this.color = {};
+ if(typeof(color.value) == 'object'){
+
+ if(color.value instanceof Array){
+ var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
+ this.color.rgb = hexToRgb(color_selected);
+ }else{
+ if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
+ this.color.rgb = {
+ r: color.value.r,
+ g: color.value.g,
+ b: color.value.b
+ }
+ }
+ if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
+ this.color.hsl = {
+ h: color.value.h,
+ s: color.value.s,
+ l: color.value.l
+ }
+ }
+ }
+
+ }
+ else if(color.value == 'random'){
+ this.color.rgb = {
+ r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
+ }
+ }
+ else if(typeof(color.value) == 'string'){
+ this.color = color;
+ this.color.rgb = hexToRgb(this.color.value);
+ }
+
+ /* opacity */
+ this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
+ if(pJS.particles.opacity.anim.enable){
+ this.opacity_status = false;
+ this.vo = pJS.particles.opacity.anim.speed / 100;
+ if(!pJS.particles.opacity.anim.sync){
+ this.vo = this.vo * Math.random();
+ }
+ }
+
+ /* animation - velocity for speed */
+ var velbase = {}
+ switch(pJS.particles.move.direction){
+ case 'top':
+ velbase = { x:0, y:-1 };
+ break;
+ case 'top-right':
+ velbase = { x:0.5, y:-0.5 };
+ break;
+ case 'right':
+ velbase = { x:1, y:-0 };
+ break;
+ case 'bottom-right':
+ velbase = { x:0.5, y:0.5 };
+ break;
+ case 'bottom':
+ velbase = { x:0, y:1 };
+ break;
+ case 'bottom-left':
+ velbase = { x:-0.5, y:1 };
+ break;
+ case 'left':
+ velbase = { x:-1, y:0 };
+ break;
+ case 'top-left':
+ velbase = { x:-0.5, y:-0.5 };
+ break;
+ default:
+ velbase = { x:0, y:0 };
+ break;
+ }
+
+ if(pJS.particles.move.straight){
+ this.vx = velbase.x;
+ this.vy = velbase.y;
+ if(pJS.particles.move.random){
+ this.vx = this.vx * (Math.random());
+ this.vy = this.vy * (Math.random());
+ }
+ }else{
+ this.vx = velbase.x + Math.random()-0.5;
+ this.vy = velbase.y + Math.random()-0.5;
+ }
+
+ // var theta = 2.0 * Math.PI * Math.random();
+ // this.vx = Math.cos(theta);
+ // this.vy = Math.sin(theta);
+
+ this.vx_i = this.vx;
+ this.vy_i = this.vy;
+
+
+
+ /* if shape is image */
+
+ var shape_type = pJS.particles.shape.type;
+ if(typeof(shape_type) == 'object'){
+ if(shape_type instanceof Array){
+ var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
+ this.shape = shape_selected;
+ }
+ }else{
+ this.shape = shape_type;
+ }
+
+ if(this.shape == 'image'){
+ var sh = pJS.particles.shape;
+ this.img = {
+ src: sh.image.src,
+ ratio: sh.image.width / sh.image.height
+ }
+ if(!this.img.ratio) this.img.ratio = 1;
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
+ pJS.fn.vendors.createSvgImg(this);
+ if(pJS.tmp.pushing){
+ this.img.loaded = false;
+ }
+ }
+ }
+
+
+
+ };
+
+
+ pJS.fn.particle.prototype.draw = function() {
+
+ var p = this;
+
+ if(p.radius_bubble != undefined){
+ var radius = p.radius_bubble;
+ }else{
+ var radius = p.radius;
+ }
+
+ if(p.opacity_bubble != undefined){
+ var opacity = p.opacity_bubble;
+ }else{
+ var opacity = p.opacity;
+ }
+
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
+ }
+
+ pJS.canvas.ctx.fillStyle = color_value;
+ pJS.canvas.ctx.beginPath();
+
+ switch(p.shape){
+
+ case 'circle':
+ pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
+ break;
+
+ case 'edge':
+ pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
+ break;
+
+ case 'triangle':
+ pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
+ break;
+
+ case 'polygon':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
+ p.y - radius / (2.66/3.5), // startY
+ radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 1 // sideCountDenominator
+ );
+ break;
+
+ case 'star':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
+ p.y - radius / (2*2.66/3.5), // startY
+ radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 2 // sideCountDenominator
+ );
+ break;
+
+ case 'image':
+
+ function draw(){
+ pJS.canvas.ctx.drawImage(
+ img_obj,
+ p.x-radius,
+ p.y-radius,
+ radius*2,
+ radius*2 / p.img.ratio
+ );
+ }
+
+ if(pJS.tmp.img_type == 'svg'){
+ var img_obj = p.img.obj;
+ }else{
+ var img_obj = pJS.tmp.img_obj;
+ }
+
+ if(img_obj){
+ draw();
+ }
+
+ break;
+
+ }
+
+ pJS.canvas.ctx.closePath();
+
+ if(pJS.particles.shape.stroke.width > 0){
+ pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
+ pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
+ pJS.canvas.ctx.stroke();
+ }
+
+ pJS.canvas.ctx.fill();
+
+ };
+
+
+ pJS.fn.particlesCreate = function(){
+ for(var i = 0; i < pJS.particles.number.value; i++) {
+ pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
+ }
+ };
+
+ pJS.fn.particlesUpdate = function(){
+
+ for(var i = 0; i < pJS.particles.array.length; i++){
+
+ /* the particle */
+ var p = pJS.particles.array[i];
+
+ // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
+ // var f = -BANG_SIZE / d;
+ // if ( d < BANG_SIZE ) {
+ // var t = Math.atan2( dy, dx );
+ // p.vx = f * Math.cos(t);
+ // p.vy = f * Math.sin(t);
+ // }
+
+ /* move the particle */
+ if(pJS.particles.move.enable){
+ var ms = pJS.particles.move.speed/2;
+ p.x += p.vx * ms;
+ p.y += p.vy * ms;
+ }
+
+ /* change opacity status */
+ if(pJS.particles.opacity.anim.enable) {
+ if(p.opacity_status == true) {
+ if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
+ p.opacity += p.vo;
+ }else {
+ if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
+ p.opacity -= p.vo;
+ }
+ if(p.opacity < 0) p.opacity = 0;
+ }
+
+ /* change size */
+ if(pJS.particles.size.anim.enable){
+ if(p.size_status == true){
+ if(p.radius >= pJS.particles.size.value) p.size_status = false;
+ p.radius += p.vs;
+ }else{
+ if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
+ p.radius -= p.vs;
+ }
+ if(p.radius < 0) p.radius = 0;
+ }
+
+ /* change particle position if it is out of canvas */
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var new_pos = {
+ x_left: p.radius,
+ x_right: pJS.canvas.w,
+ y_top: p.radius,
+ y_bottom: pJS.canvas.h
+ }
+ }else{
+ var new_pos = {
+ x_left: -p.radius,
+ x_right: pJS.canvas.w + p.radius,
+ y_top: -p.radius,
+ y_bottom: pJS.canvas.h + p.radius
+ }
+ }
+
+ if(p.x - p.radius > pJS.canvas.w){
+ p.x = new_pos.x_left;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ else if(p.x + p.radius < 0){
+ p.x = new_pos.x_right;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ if(p.y - p.radius > pJS.canvas.h){
+ p.y = new_pos.y_top;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+ else if(p.y + p.radius < 0){
+ p.y = new_pos.y_bottom;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+
+ /* out of canvas modes */
+ switch(pJS.particles.move.out_mode){
+ case 'bounce':
+ if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (p.x - p.radius < 0) p.vx = -p.vx;
+ if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (p.y - p.radius < 0) p.vy = -p.vy;
+ break;
+ }
+
+ /* events */
+ if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
+ pJS.fn.modes.grabParticle(p);
+ }
+
+ if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.bubbleParticle(p);
+ }
+
+ if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.repulseParticle(p);
+ }
+
+ /* interaction auto between particles */
+ if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
+ for(var j = i + 1; j < pJS.particles.array.length; j++){
+ var p2 = pJS.particles.array[j];
+
+ /* link particles */
+ if(pJS.particles.line_linked.enable){
+ pJS.fn.interact.linkParticles(p,p2);
+ }
+
+ /* attract particles */
+ if(pJS.particles.move.attract.enable){
+ pJS.fn.interact.attractParticles(p,p2);
+ }
+
+ /* bounce particles */
+ if(pJS.particles.move.bounce){
+ pJS.fn.interact.bounceParticles(p,p2);
+ }
+
+ }
+ }
+
+
+ }
+
+ };
+
+ pJS.fn.particlesDraw = function(){
+
+ /* clear canvas */
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+
+ /* update each particles param */
+ pJS.fn.particlesUpdate();
+
+ /* draw each particle */
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p = pJS.particles.array[i];
+ p.draw();
+ }
+
+ };
+
+ pJS.fn.particlesEmpty = function(){
+ pJS.particles.array = [];
+ };
+
+ pJS.fn.particlesRefresh = function(){
+
+ /* init all */
+ cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
+ cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ pJS.tmp.source_svg = undefined;
+ pJS.tmp.img_obj = undefined;
+ pJS.tmp.count_svg = 0;
+ pJS.fn.particlesEmpty();
+ pJS.fn.canvasClear();
+
+ /* restart */
+ pJS.fn.vendors.start();
+
+ };
+
+
+ /* ---------- pJS functions - particles interaction ------------ */
+
+ pJS.fn.interact.linkParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ /* draw a line between p1 and p2 if the distance between them is under the config distance */
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p1.x, p1.y);
+ pJS.canvas.ctx.lineTo(p2.x, p2.y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.interact.attractParticles = function(p1, p2){
+
+ /* condensed particles */
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var ax = dx/(pJS.particles.move.attract.rotateX*1000),
+ ay = dy/(pJS.particles.move.attract.rotateY*1000);
+
+ p1.vx -= ax;
+ p1.vy -= ay;
+
+ p2.vx += ax;
+ p2.vy += ay;
+
+ }
+
+
+ }
+
+
+ pJS.fn.interact.bounceParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy),
+ dist_p = p1.radius+p2.radius;
+
+ if(dist <= dist_p){
+ p1.vx = -p1.vx;
+ p1.vy = -p1.vy;
+
+ p2.vx = -p2.vx;
+ p2.vy = -p2.vy;
+ }
+
+ }
+
+
+ /* ---------- pJS functions - modes events ------------ */
+
+ pJS.fn.modes.pushParticles = function(nb, pos){
+
+ pJS.tmp.pushing = true;
+
+ for(var i = 0; i < nb; i++){
+ pJS.particles.array.push(
+ new pJS.fn.particle(
+ pJS.particles.color,
+ pJS.particles.opacity.value,
+ {
+ 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
+ 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
+ }
+ )
+ )
+ if(i == nb-1){
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+ pJS.tmp.pushing = false;
+ }
+ }
+
+ };
+
+
+ pJS.fn.modes.removeParticles = function(nb){
+
+ pJS.particles.array.splice(0, nb);
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+
+ };
+
+
+ pJS.fn.modes.bubbleParticle = function(p){
+
+ /* on hover event */
+ if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
+
+ function init(){
+ p.opacity_bubble = p.opacity;
+ p.radius_bubble = p.radius;
+ }
+
+ /* mousemove - check ratio */
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+
+ if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
+
+ /* size */
+ if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
+
+ if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
+ var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
+ if(size >= 0){
+ p.radius_bubble = size;
+ }
+ }else{
+ var dif = p.radius - pJS.interactivity.modes.bubble.size,
+ size = p.radius - (dif*ratio);
+ if(size > 0){
+ p.radius_bubble = size;
+ }else{
+ p.radius_bubble = 0;
+ }
+ }
+
+ }
+
+ /* opacity */
+ if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
+
+ if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
+ var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
+ if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }else{
+ var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
+ if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }
+
+ }
+
+ }
+
+ }else{
+ init();
+ }
+
+
+ /* mouseleave */
+ if(pJS.interactivity.status == 'mouseleave'){
+ init();
+ }
+
+ }
+
+ /* on click event */
+ else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+
+
+ if(pJS.tmp.bubble_clicking){
+ var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration){
+ pJS.tmp.bubble_duration_end = true;
+ }
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration*2){
+ pJS.tmp.bubble_clicking = false;
+ pJS.tmp.bubble_duration_end = false;
+ }
+ }
+
+
+ function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
+
+ if(bubble_param != particles_param){
+
+ if(!pJS.tmp.bubble_duration_end){
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+ if(p_obj_bubble != undefined) var obj = p_obj_bubble;
+ else var obj = p_obj;
+ if(obj != bubble_param){
+ var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }else{
+ if(id == 'size') p.radius_bubble = undefined;
+ if(id == 'opacity') p.opacity_bubble = undefined;
+ }
+ }else{
+ if(p_obj_bubble != undefined){
+ var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
+ dif = bubble_param - value_tmp;
+ value = bubble_param + dif;
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }
+
+ }
+
+ }
+
+ if(pJS.tmp.bubble_clicking){
+ /* size */
+ process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
+ /* opacity */
+ process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.modes.repulseParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
+ repulseRadius = pJS.interactivity.modes.repulse.distance,
+ velocity = 100,
+ repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
+
+ var pos = {
+ x: p.x + normVec.x * repulseFactor,
+ y: p.y + normVec.y * repulseFactor
+ }
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
+ if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
+ }else{
+ p.x = pos.x;
+ p.y = pos.y;
+ }
+
+ }
+
+
+ else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+
+ if(!pJS.tmp.repulse_finish){
+ pJS.tmp.repulse_count++;
+ if(pJS.tmp.repulse_count == pJS.particles.array.length){
+ pJS.tmp.repulse_finish = true;
+ }
+ }
+
+ if(pJS.tmp.repulse_clicking){
+
+ var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
+
+ var dx = pJS.interactivity.mouse.click_pos_x - p.x,
+ dy = pJS.interactivity.mouse.click_pos_y - p.y,
+ d = dx*dx + dy*dy;
+
+ var force = -repulseRadius / d * 1;
+
+ function process(){
+
+ var f = Math.atan2(dy,dx);
+ p.vx = force * Math.cos(f);
+ p.vy = force * Math.sin(f);
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var pos = {
+ x: p.x + p.vx,
+ y: p.y + p.vy
+ }
+ if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (pos.x - p.radius < 0) p.vx = -p.vx;
+ if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (pos.y - p.radius < 0) p.vy = -p.vy;
+ }
+
+ }
+
+ // default
+ if(d <= repulseRadius){
+ process();
+ }
+
+ // bang - slow motion mode
+ // if(!pJS.tmp.repulse_finish){
+ // if(d <= repulseRadius){
+ // process();
+ // }
+ // }else{
+ // process();
+ // }
+
+
+ }else{
+
+ if(pJS.tmp.repulse_clicking == false){
+
+ p.vx = p.vx_i;
+ p.vy = p.vy_i;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ pJS.fn.modes.grabParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ /* draw a line between the cursor and the particle if the distance between them is under the config distance */
+ if(dist_mouse <= pJS.interactivity.modes.grab.distance){
+
+ var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p.x, p.y);
+ pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ }
+
+ };
+
+
+
+ /* ---------- pJS functions - vendors ------------ */
+
+ pJS.fn.vendors.eventsListeners = function(){
+
+ /* events target element */
+ if(pJS.interactivity.detect_on == 'window'){
+ pJS.interactivity.el = window;
+ }else{
+ pJS.interactivity.el = pJS.canvas.el;
+ }
+
+
+ /* detect mouse pos - on hover / click event */
+ if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
+
+ /* el on mousemove */
+ pJS.interactivity.el.addEventListener('mousemove', function(e){
+
+ if(pJS.interactivity.el == window){
+ var pos_x = e.clientX,
+ pos_y = e.clientY;
+ }
+ else{
+ var pos_x = e.offsetX || e.clientX,
+ pos_y = e.offsetY || e.clientY;
+ }
+
+ pJS.interactivity.mouse.pos_x = pos_x;
+ pJS.interactivity.mouse.pos_y = pos_y;
+
+ if(pJS.tmp.retina){
+ pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
+ pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
+ }
+
+ pJS.interactivity.status = 'mousemove';
+
+ });
+
+ /* el on onmouseleave */
+ pJS.interactivity.el.addEventListener('mouseleave', function(e){
+
+ pJS.interactivity.mouse.pos_x = null;
+ pJS.interactivity.mouse.pos_y = null;
+ pJS.interactivity.status = 'mouseleave';
+
+ });
+
+ }
+
+ /* on click event */
+ if(pJS.interactivity.events.onclick.enable){
+
+ pJS.interactivity.el.addEventListener('click', function(){
+
+ pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
+ pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
+ pJS.interactivity.mouse.click_time = new Date().getTime();
+
+ if(pJS.interactivity.events.onclick.enable){
+
+ switch(pJS.interactivity.events.onclick.mode){
+
+ case 'push':
+ if(pJS.particles.move.enable){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }else{
+ if(pJS.interactivity.modes.push.particles_nb == 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }
+ else if(pJS.interactivity.modes.push.particles_nb > 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
+ }
+ }
+ break;
+
+ case 'remove':
+ pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
+ break;
+
+ case 'bubble':
+ pJS.tmp.bubble_clicking = true;
+ break;
+
+ case 'repulse':
+ pJS.tmp.repulse_clicking = true;
+ pJS.tmp.repulse_count = 0;
+ pJS.tmp.repulse_finish = false;
+ setTimeout(function(){
+ pJS.tmp.repulse_clicking = false;
+ }, pJS.interactivity.modes.repulse.duration*1000)
+ break;
+
+ }
+
+ }
+
+ });
+
+ }
+
+
+ };
+
+ pJS.fn.vendors.densityAutoParticles = function(){
+
+ if(pJS.particles.number.density.enable){
+
+ /* calc area */
+ var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
+ if(pJS.tmp.retina){
+ area = area/(pJS.canvas.pxratio*2);
+ }
+
+ /* calc number of particles based on density area */
+ var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
+
+ /* add or remove X particles */
+ var missing_particles = pJS.particles.array.length - nb_particles;
+ if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
+ else pJS.fn.modes.removeParticles(missing_particles);
+
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkOverlap = function(p1, position){
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p2 = pJS.particles.array[i];
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= p1.radius + p2.radius){
+ p1.x = position ? position.x : Math.random() * pJS.canvas.w;
+ p1.y = position ? position.y : Math.random() * pJS.canvas.h;
+ pJS.fn.vendors.checkOverlap(p1);
+ }
+ }
+ };
+
+
+ pJS.fn.vendors.createSvgImg = function(p){
+
+ /* set color to svg element */
+ var svgXml = pJS.tmp.source_svg,
+ rgbHex = /#([0-9A-F]{3,6})/gi,
+ coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
+ }
+ return color_value;
+ });
+
+ /* prepare to create img with colored svg */
+ var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
+ DOMURL = window.URL || window.webkitURL || window,
+ url = DOMURL.createObjectURL(svg);
+
+ /* create particle img obj */
+ var img = new Image();
+ img.addEventListener('load', function(){
+ p.img.obj = img;
+ p.img.loaded = true;
+ DOMURL.revokeObjectURL(url);
+ pJS.tmp.count_svg++;
+ });
+ img.src = url;
+
+ };
+
+
+ pJS.fn.vendors.destroypJS = function(){
+ cancelAnimationFrame(pJS.fn.drawAnimFrame);
+ canvas_el.remove();
+ pJSDom = null;
+ };
+
+
+ pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
+
+ // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
+ var sideCount = sideCountNumerator * sideCountDenominator;
+ var decimalSides = sideCountNumerator / sideCountDenominator;
+ var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
+ var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
+ c.save();
+ c.beginPath();
+ c.translate(startX, startY);
+ c.moveTo(0,0);
+ for (var i = 0; i < sideCount; i++) {
+ c.lineTo(sideLength,0);
+ c.translate(sideLength,0);
+ c.rotate(interiorAngle);
+ }
+ //c.stroke();
+ c.fill();
+ c.restore();
+
+ };
+
+ pJS.fn.vendors.exportImg = function(){
+ window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
+ };
+
+
+ pJS.fn.vendors.loadImg = function(type){
+
+ pJS.tmp.img_error = undefined;
+
+ if(pJS.particles.shape.image.src != ''){
+
+ if(type == 'svg'){
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', pJS.particles.shape.image.src);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ pJS.tmp.source_svg = data.currentTarget.response;
+ pJS.fn.vendors.checkBeforeDraw();
+ }else{
+ console.log('Error pJS - Image not found');
+ pJS.tmp.img_error = true;
+ }
+ }
+ }
+ xhr.send();
+
+ }else{
+
+ var img = new Image();
+ img.addEventListener('load', function(){
+ pJS.tmp.img_obj = img;
+ pJS.fn.vendors.checkBeforeDraw();
+ });
+ img.src = pJS.particles.shape.image.src;
+
+ }
+
+ }else{
+ console.log('Error pJS - No image.src');
+ pJS.tmp.img_error = true;
+ }
+
+ };
+
+
+ pJS.fn.vendors.draw = function(){
+
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg'){
+
+ if(pJS.tmp.count_svg >= pJS.particles.number.value){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ //console.log('still loading...');
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }else{
+
+ if(pJS.tmp.img_obj != undefined){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }
+
+ }else{
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkBeforeDraw = function(){
+
+ // if shape is image
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
+ pJS.tmp.checkAnimFrame = requestAnimFrame(check);
+ }else{
+ //console.log('images loaded! cancel check');
+ cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
+ if(!pJS.tmp.img_error){
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ }
+
+ }else{
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ };
+
+
+ pJS.fn.vendors.init = function(){
+
+ /* init canvas + particles */
+ pJS.fn.retinaInit();
+ pJS.fn.canvasInit();
+ pJS.fn.canvasSize();
+ pJS.fn.canvasPaint();
+ pJS.fn.particlesCreate();
+ pJS.fn.vendors.densityAutoParticles();
+
+ /* particles.line_linked - convert hex colors to rgb */
+ pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
+
+ };
+
+
+ pJS.fn.vendors.start = function(){
+
+ if(isInArray('image', pJS.particles.shape.type)){
+ pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
+ pJS.fn.vendors.loadImg(pJS.tmp.img_type);
+ }else{
+ pJS.fn.vendors.checkBeforeDraw();
+ }
+
+ };
+
+
+
+
+ /* ---------- pJS - start ------------ */
+
+
+ pJS.fn.vendors.eventsListeners();
+
+ pJS.fn.vendors.start();
+
+
+
+};
+
+/* ---------- global functions - vendors ------------ */
+
+Object.deepExtend = function(destination, source) {
+ for (var property in source) {
+ if (source[property] && source[property].constructor &&
+ source[property].constructor === Object) {
+ destination[property] = destination[property] || {};
+ arguments.callee(destination[property], source[property]);
+ } else {
+ destination[property] = source[property];
+ }
+ }
+ return destination;
+};
+
+window.requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback){
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+
+window.cancelRequestAnimFrame = ( function() {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelRequestAnimationFrame ||
+ window.mozCancelRequestAnimationFrame ||
+ window.oCancelRequestAnimationFrame ||
+ window.msCancelRequestAnimationFrame ||
+ clearTimeout
+} )();
+
+function hexToRgb(hex){
+ // By Tim Down - http://stackoverflow.com/a/5624139/3493650
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+};
+
+function clamp(number, min, max) {
+ return Math.min(Math.max(number, min), max);
+};
+
+function isInArray(value, array) {
+ return array.indexOf(value) > -1;
+}
+
+
+/* ---------- particles.js functions - start ------------ */
+
+window.pJSDom = [];
+
+window.particlesJS = function(tag_id, params){
+
+ //console.log(params);
+
+ /* no string id? so it's object params, and set the id with default id */
+ if(typeof(tag_id) != 'string'){
+ params = tag_id;
+ tag_id = 'particles-js';
+ }
+
+ /* no id? set the id to default id */
+ if(!tag_id){
+ tag_id = 'particles-js';
+ }
+
+ /* pJS elements */
+ var pJS_tag = document.getElementById(tag_id),
+ pJS_canvas_class = 'particles-js-canvas-el',
+ exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
+
+ /* remove canvas if exists into the pJS target tag */
+ if(exist_canvas.length){
+ while(exist_canvas.length > 0){
+ pJS_tag.removeChild(exist_canvas[0]);
+ }
+ }
+
+ /* create canvas element */
+ var canvas_el = document.createElement('canvas');
+ canvas_el.className = pJS_canvas_class;
+
+ /* set size canvas */
+ canvas_el.style.width = "100%";
+ canvas_el.style.height = "100%";
+
+ /* append canvas */
+ var canvas = document.getElementById(tag_id).appendChild(canvas_el);
+
+ /* launch particle.js */
+ if(canvas != null){
+ pJSDom.push(new pJS(tag_id, params));
+ }
+
+};
+
+window.particlesJS.load = function(tag_id, path_config_json, callback){
+
+ /* load json config */
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path_config_json);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ var params = JSON.parse(data.currentTarget.response);
+ window.particlesJS(tag_id, params);
+ if(callback) callback();
+ }else{
+ console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
+ console.log('Error pJS - File config not found');
+ }
+ }
+ };
+ xhr.send();
+
+};
\ No newline at end of file
diff --git a/docs/scripts/home/particles.js b/docs/scripts/home/particles.js
new file mode 100644
index 0000000..d5dad0b
--- /dev/null
+++ b/docs/scripts/home/particles.js
@@ -0,0 +1,91 @@
+particlesJS('particles-js', {
+ "particles": {
+ "number": {
+ "value":30,
+ "density": {
+ "enable":true,
+ "value_area":800
+ }
+ },
+ "color": { "value": "#ffffff" },
+ "shape": {
+ "type": "circle",
+ "stroke": { "width": 0, "color":"#000000" },
+ "polygon": { "nb_sides": 5 },
+ "image": { "src": "img/github.svg", "width": 100, "height": 100}
+ },
+ "opacity": {
+ "value": 0.5,
+ "random": false,
+ "anim": {
+ "enable": false,
+ "speed": 1,
+ "opacity_min": 0.1,
+ "sync": false
+ }
+ },
+ "size": {
+ "value": 5,
+ "random": true,
+ "anim": {
+ "enable": false,
+ "speed": 40,
+ "size_min": 0.1,
+ "sync": false
+ }
+ },
+ "line_linked": {
+ "enable": false,
+ "distance": 150,
+ "color": "#ffffff",
+ "opacity": 0.4,
+ "width": 1
+ },
+ "move": {
+ "enable": true,
+ "speed": 6,
+ "direction": "none",
+ "random": true,
+ "straight": false,
+ "out_mode": "out",
+ "attract": {
+ "enable": false,
+ "rotateX": 600,
+ "rotateY":1200
+ }
+ }
+ },
+ "interactivity": {
+ "detect_on": "canvas",
+ "events": {
+ "onhover": { "enable": false, "mode": "repulse" },
+ "onclick": { "enable": true, "mode": "push" },
+ "resize": true
+ },
+ "modes": {
+ "grab": {
+ "distance": 400,
+ "line_linked": { "opacity": 1 }
+ },
+ "bubble": {
+ "distance": 400,
+ "size": 40,
+ "duration": 2,
+ "opacity": 8,
+ "speed": 3
+ },
+ "repulse": { "distance": 200 },
+ "push":{ "particles_nb": 4 },
+ "remove":{ "particles_nb": 2 }
+ }
+ },
+ "retina_detect": true,
+ "config_demo": {
+ "hide_card": false,
+ "background_color": "#b61924",
+ "background_image": "",
+ "background_position": "50% 50%",
+ "background_repeat": "no-repeat",
+ "background_size": "cover"
+ }
+});
\ No newline at end of file
diff --git a/docs/scripts/home/typewrite.js b/docs/scripts/home/typewrite.js
new file mode 100644
index 0000000..665cd4d
--- /dev/null
+++ b/docs/scripts/home/typewrite.js
@@ -0,0 +1,57 @@
+(() => {
+ var TxtType = function (el, toRotate, period) {
+ this.toRotate = toRotate;
+ this.el = el;
+ this.loopNum = 0;
+ this.period = parseInt(period, 10) || 2000;
+ this.txt = '';
+ this.tick();
+ this.isDeleting = false;
+ };
+
+ TxtType.prototype.tick = function () {
+ var i = this.loopNum % this.toRotate.length;
+ var fullTxt = this.toRotate[i];
+ if (this.isDeleting) {
+ this.txt = fullTxt.substring(0, this.txt.length - 1);
+ } else {
+ this.txt = fullTxt.substring(0, this.txt.length + 1);
+ }
+ this.el.innerHTML = this.txt;
+ var that = this;
+ var delta = 200 - Math.random() * 100;
+ if (this.isDeleting) { delta /= 2; }
+ if (!this.isDeleting && this.txt === fullTxt) {
+ delta = this.period;
+ this.isDeleting = true;
+ } else if (this.isDeleting && this.txt === '') {
+ this.isDeleting = false;
+ this.loopNum++;
+ delta = 500;
+ //emit custom event
+ const customEvent = new CustomEvent('typewriter-next')
+ customEvent.index = this.loopNum % this.toRotate.length
+ customEvent.text = this.toRotate[this.loopNum % this.toRotate.length]
+ window.dispatchEvent(customEvent)
+ }
+ setTimeout(function () {
+ that.tick();
+ }, delta);
+ };
+
+ function typewrite() {
+ if (toRotate === 'undefined') {
+ changeText()
+ }
+ else
+ var elements = document.getElementsByClassName('typewrite');
+ for (var i = 0; i < elements.length; i++) {
+ var toRotate = elements[i].getAttribute('data-values');
+ var period = elements[i].getAttribute('data-period');
+ if (toRotate) {
+ new TxtType(elements[i], toRotate.split(","), period);
+ }
+ }
+ };
+ window.addEventListener('load', typewrite);
+})()
\ No newline at end of file
diff --git a/docs/scripts/lib/blockapi.js b/docs/scripts/lib/blockapi.js
new file mode 100644
index 0000000..6292681
--- /dev/null
+++ b/docs/scripts/lib/blockapi.js
@@ -0,0 +1,123 @@
+window.blockapi = {
+ async read(contract, method, ...args) {
+ return await contract.methods[method](...args).call()
+ },
+
+ async write(contract, account, method, value, ...args) {
+ const params = {
+ to: contracts.address,
+ from: account,
+ data: contract.methods[method](...args).encodeABI(),
+ }
+
+ if (value) params.value = String(value)
+
+ return await window.ethereum.request({
+ method: 'eth_sendTransaction',
+ params: [params]
+ })
+ },
+
+ toEther(web3, num, format) {
+ if (format === 'string') {
+ return web3.utils.fromWei(String(num)).toString()
+ } else if (format === 'comma') {
+ return web3.utils.fromWei(String(num)).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+ } else if (format === 'int') {
+ return parseInt(web3.utils.fromWei(String(num)).toString());
+ }
+ return web3.utils.fromWei(String(num))
+ },
+
+ toWei(web3, num) {
+ return web3.utils.toWei(String(num)).toString()
+ },
+
+ connect(blockmetadata, connected, disconnected) {
+ const validate = async(action, param) => {
+ if (action === 'accountsChanged') {
+ if (!Array.isArray(param) || param.length === 0) {
+ return disconnected()
+ }
+ }
+ if (!window.ethereum?.isMetaMask) {
+ return disconnected({
+ connected: false,
+ message: 'Please install MetaMask and refresh this page.'
+ })
+ }
+ try {
+ const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
+ const networkId = await window.ethereum.request({ method: 'net_version' });
+ if (networkId == blockmetadata.chain_id) {
+ const web3 = new Web3(window.ethereum)
+ const results = {
+ account: accounts[0],
+ web3: web3
+ }
+
+ if (Array.isArray(blockmetadata.contract?.abi)
+ && typeof blockmetadata.contract?.address === 'string'
+ ) {
+ results.contract = new web3.eth.Contract(
+ blockmetadata.contract.abi,
+ blockmetadata.contract.address
+ )
+ }
+
+ if (typeof blockmetadata.contracts === 'object') {
+ for (const key in blockmetadata.contracts) {
+ if (Array.isArray(blockmetadata.contracts[key]?.abi)
+ && typeof blockmetadata.contracts[key]?.address === 'string'
+ ) {
+ results[key] = new web3.eth.Contract(
+ blockmetadata.contracts[key].abi,
+ blockmetadata.contracts[key].address
+ )
+ }
+ }
+ }
+ return connected(results)
+ }
+
+ return disconnected(new Error(`Please change network to ${blockmetadata.chain_name}.`))
+ } catch (e) {
+ return disconnected(e)
+ }
+ }
+
+ if (window.ethereum?.isMetaMask) {
+ window.ethereum.on('connect', validate.bind(null, 'connect'))
+ window.ethereum.on('disconnect', disconnected)
+ window.ethereum.on('chainChanged', validate.bind(null, 'chainChanged'))
+ window.ethereum.on('accountsChanged', validate.bind(null, 'accountsChanged'))
+ }
+
+ validate('init')
+ },
+
+ notify(type, message, timeout = 5000) {
+ Array.from(document.querySelectorAll('div.notification')).forEach((notification) => {
+ if (notification.mounted) {
+ document.body.removeChild(notification)
+ notification.mounted = false
+ }
+ })
+ const container = document.createElement('div')
+ container.className = `notification notification-${type}`
+ container.innerHTML = message
+ container.mounted = true
+ document.body.appendChild(container)
+ container.addEventListener('click', () => {
+ document.body.removeChild(container)
+ container.mounted = false
+ })
+
+ setTimeout(() => {
+ if (container.mounted) {
+ document.body.removeChild(container)
+ container.mounted = false
+ }
+ }, timeout)
+ }
+}
\ No newline at end of file
diff --git a/docs/scripts/lib/doon.js b/docs/scripts/lib/doon.js
new file mode 100644
index 0000000..d29322d
--- /dev/null
+++ b/docs/scripts/lib/doon.js
@@ -0,0 +1,50 @@
+window.doon = function(selector) {
+ Array.from(
+ document.querySelectorAll(selector)
+ ).forEach(function(container) {
+ Array.from(
+ container.querySelectorAll('*[data-do]')
+ ).forEach(function(origin) {
+ let actions = origin.getAttribute('data-do');
+ if(!actions || origin.getAttribute('data-doon')) {
+ return;
+ }
+
+ actions = actions.split('|');
+ origin.setAttribute('data-doon', true)
+
+ const event = origin.getAttribute('data-on');
+ const target = origin.getAttribute('data-doon-target') || origin;
+
+ //trigger init
+ actions.forEach(function(action) {
+ const event = new Event(`${action}-init`)
+ event.for = target
+ window.dispatchEvent(event)
+ });
+
+ if(!event) {
+ return;
+ }
+
+ event.split('|').forEach(function(event) {
+ target.addEventListener(event, function(e) {
+ actions.some(function(action) {
+ //mod the custom event type
+ const customEvent = new e.constructor(action + '-' + event, e)
+ customEvent.originalEvent = e
+ customEvent.for = target
+ //pass it along
+ window.dispatchEvent(customEvent)
+ return e.return === false
+ });
+
+ //so you can stop a form
+ if (e.return === false) {
+ return false;
+ }
+ });
+ });
+ });
+ });
+}
\ No newline at end of file
diff --git a/docs/site.webmanifest b/docs/site.webmanifest
new file mode 100644
index 0000000..0c08bf9
--- /dev/null
+++ b/docs/site.webmanifest
@@ -0,0 +1,14 @@
+{
+ "name": "",
+ "short_name": "",
+ "icons": [
+ {
+ "src": "/images/favicon/android-chrome-144x144.png",
+ "sizes": "144x144",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
diff --git a/docs/styles/index.css b/docs/styles/index.css
new file mode 100644
index 0000000..68f268c
--- /dev/null
+++ b/docs/styles/index.css
@@ -0,0 +1,356 @@
+html, body {
+ height: 100%;
+}
+
+.head {
+ position: relative;
+ z-index: 1;
+}
+
+.box {
+ background: rgba(255, 255, 255, .03);
+ border: solid 1px rgba(255, 255, 255, .1);
+ border-radius: 20px;
+ box-shadow: 1px 1px 8px 1px rgb(0 0 0 / 10%);
+ display: block;
+ padding: 30px;
+ position: relative;
+}
+
+.section .container {
+ margin: auto;
+ max-width: 900px;
+}
+
+.section h2 {
+ color: #FFFFFF;
+ font-size: 24px;
+ margin: 0 0 20px;
+ text-transform: uppercase;
+}
+
+.section h3 {
+ color: rgb(251, 191, 36);
+ font-size: 16px;
+ margin: 0;
+ text-transform: uppercase;
+}
+
+.section .btn-primary {
+ font-weight: bold;
+ margin-top: 20px;
+ padding: 20px 40px;
+ text-transform: uppercase;
+}
+
+.section .btn-outline-primary {
+ color: #FFFFFF;
+ font-weight: normal;
+ padding: 10px 40px;
+ text-transform: uppercase;
+}
+
+.section-1 {
+ background-image: url(/images/bg-space.png);
+ background-image: url(/images/bg-space.png), linear-gradient(#eb01a5, #d13531);
+ background-position: center bottom;
+ background-size: cover;
+ height: 100%;
+ margin-top: -90px;
+ padding-top: 90px;
+ position: relative;
+}
+
+.section-1 canvas {
+ position: absolute;
+ top: 0;
+}
+
+.section-1 .container {
+ display: flex;
+ height: 600px;
+ padding: 100px 20px 0;
+ position: relative;
+ z-index: 2;
+}
+
+.section-1 .left {
+ flex-grow: 1;
+ padding: 80px 40px 0 0;
+}
+
+.section-1 h1 {
+ color: rgb(251, 191, 36);
+ font-size: 16px;
+ margin: 0;
+}
+
+.section-1 h2 {
+ color: #FFFFFF;
+ font-size: 30px;
+ margin: 0 0 20px;
+ text-transform: none;
+ white-space: nowrap;
+}
+
+.section-1 h2 .typewrite {
+ display: block;
+ min-height: 42px;
+}
+
+.section-1 .chains {
+ white-space: nowrap;
+}
+
+.section-1 .chains .chain {
+ background-image: url(/images/sprite-chains.png);
+ background-repeat: no-repeat;
+ background-size: 120px 120px;
+ display: inline-block;
+ height: 40px;
+ margin: 0 5px;
+ width: 40px;
+}
+
+.section-1 .chains .chain-1 {
+ background-position: 0 0;
+}
+
+.section-1 .chains .chain-2 {
+ background-position: -40px 0;
+}
+
+.section-1 .chains .chain-3 {
+ background-position: -80px 0;
+}
+
+.section-1 .chains .chain-4 {
+ background-position: 0 -40px;
+}
+
+.section-1 .chains .chain-5 {
+ background-position: -40px -40px;
+}
+
+.section-1 .chains .chain-6 {
+ background-position: -80px -40px;
+}
+
+.section-1 .chains .chain-7 {
+ background-position: 0 -80px;
+}
+
+.section-1 .chains .chain-8 {
+ background-position: -40px -80px;
+}
+
+.section-1 .chains .chain-9 {
+ background-position: -80px -80px;
+}
+
+.section-1 .right {
+ overflow: hidden;
+ position: relative;
+ width: 450px;
+}
+
+.section-1 .right img {
+ position: absolute;
+ transition: 1s ease-in-out;
+ right: -450px;
+ width: 100%;
+}
+
+.section-1 .right img.active {
+ right: 0
+}
+
+.section-2 {
+ background-image: url(/images/bg-gns-1.jpg);
+ background-position: bottom;
+ background-size: cover;
+}
+
+.section-2 .container {
+ display: flex;
+ padding: 80px 0 200px;
+}
+
+.section-2 .left {
+ padding: 20px 40px 0 0;
+ width: calc(50% - 40px);
+}
+
+.section-2 p {
+ padding-top: 0;
+}
+
+.section-2 .right {
+ width: 50%;;
+}
+
+.section-2 .right img {
+ width: 100%;
+}
+
+.section-3 {
+ background-color: #000000;
+ padding: 40px 0;
+}
+
+.section-3 ul {
+ padding-bottom: 20px;
+ padding-top: 20px;
+}
+
+.section-3 li {
+ color: rgb(251, 191, 36);
+ font-size: 15px;
+ line-height: 32px;
+}
+
+.section-3 .container {
+ display: flex;
+ padding-top: 40px;
+}
+
+.section-3 .left {
+ width: 50%;;
+}
+
+.section-3 .right {
+ padding-top: 150px;
+ width: 50%;;
+}
+
+.section-4 {
+ background-image: url(/images/bg-gns-2.jpg);
+ background-size: cover;
+}
+
+.section-4 .container {
+ padding-bottom: 200px;
+ padding-top: 200px;
+}
+
+.section-4 .logo {
+ float: left;
+ margin-right: 5px;
+}
+
+.section-4 h2 {
+ align-items: center;
+ color: #FFFFFF;
+ display: flex;
+ font-size: 18px;
+ justify-content: center;
+ margin-bottom: 30px;
+ text-transform: none;
+}
+
+.section-4 h2 .label {
+ color: rgb(251, 191, 36);
+ display: inline-block;
+ font-family: "Press Start 2P", sans-serif;
+ font-size: 15px;
+ margin: 2px 5px 0 0;
+}
+
+.section-4 h3 {
+ color: #FFFFFF;
+ font-size: 30px;
+ font-weight: normal;
+ padding: 0 0 10px 0;
+ text-align: center;
+ text-transform: none;
+}
+
+.section-4 form {
+ align-items: center;
+ background-color: #FFFFFF;
+ display: flex;
+ margin: auto;
+}
+
+.section-4 form > * {
+ padding-bottom: 10px;
+ padding-top: 10px;
+}
+
+.section-4 form img {
+ padding-left: 20px;
+}
+
+.section-4 form label {
+ border-right: 1px solid #666666;
+ color: #333333;
+ font-weight: bold;
+ display: block;
+ margin-right: 20px;
+ padding-right: 20px;
+}
+
+.section-4 form input {
+ border: 0;
+ border-radius: 0;
+ flex-grow: 1;
+ height: 55px;
+ padding: 0;
+}
+
+.section-4 form input:focus {
+ outline: none;
+}
+
+.section-4 form .domain {
+ color: #333333;
+ font-size: 13px;
+ font-weight: bold;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+.section-4 form button {
+ background-color: transparent;
+ border: 0;
+ border-left: 1px solid #666666;
+ border-radius: 0;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+.section-5 {
+ background-color: #111619;
+ background-image: url(/images/gcoin.png);
+ background-position: calc(100% + 100px) -100px;
+ background-repeat: no-repeat;
+ background-size: 700px;
+}
+
+.section-5 h2 {
+ margin-bottom: 0;
+}
+
+.section-5 p {
+ padding: 0;
+}
+
+.section-5 ul {
+ padding-bottom: 20px;
+}
+
+.section-5 li {
+ color: #FFFFFF;
+ font-size: 15px;
+ line-height: 32px;
+}
+
+.section-5 .container {
+ display: flex;
+ padding-bottom: 200px;
+ padding-top: 100px;
+}
+
+.section-5 .left {
+ width: 50%;
+}
\ No newline at end of file
diff --git a/docs/styles/theme.css b/docs/styles/theme.css
new file mode 100644
index 0000000..9dd6365
--- /dev/null
+++ b/docs/styles/theme.css
@@ -0,0 +1,331 @@
+html, body {
+ background-color: #222328;
+ color: #EEEEEE;
+ font-family: "Open Sans", Arial;
+ margin: 0;
+}
+
+a, a:hover, a:active, a:visited {
+ color: #EEEEEE;
+ text-decoration: none;
+}
+
+blockquote {
+ border-left: 5px solid #CCCCCC;
+ color: #CCCCCC;
+ line-height: 26px;
+ margin: 10px 0;
+ padding: 5px 20px;
+}
+
+code {
+ background: #EEEEEE;
+ display: inline-block;
+ padding: 2px 5px;
+}
+
+pre code {
+ display: block;
+ line-height: 24px;
+ padding: 0 20px;
+}
+
+.overflow pre {
+ background: #000000;
+ overflow: auto;
+ width: 100%;
+}
+
+hr {
+ border-color: #555555;
+}
+
+ul {
+ padding-left: 20px;
+}
+
+li {
+ color: #444444;
+ font-size: 13px;
+ line-height: 26px;
+ margin-bottom: 10px;
+}
+
+.hidden {
+ display: none;
+}
+
+.btn-primary {
+ background-color: #FFC600;
+ border-radius: 10px;
+ display: inline-block;
+ color: #FFFFFF;
+ padding: 5px 10px;
+}
+
+.btn-outline-primary {
+ border: 1px solid rgb(251, 191, 36);
+ display: inline-block;
+ color: rgb(251, 191, 36);
+ padding: 5px 10px;
+}
+
+.text-success {
+ color: #06a700
+}
+
+.text-warning {
+ color: #c59100
+}
+
+.text-danger {
+ color: #c20f02
+}
+
+.table {
+ border: 1px solid #444444;
+ border-spacing: 0;
+ width: 100%;
+}
+
+.table th {
+ background-color: #CCCCCC;
+ padding: 20px 5px;
+}
+
+.table td {
+ padding: 20px 5px;
+}
+
+.table.center th,
+.table.center td {
+ text-align: center;
+}
+
+.article-banner {
+ border:1px solid #444444;
+ margin: 60px 0 20px;
+ padding:50px 200px;
+}
+
+.head {
+ display: flex;
+ align-items: center;
+ margin: auto;
+ max-width: 900px;
+ padding: 20px;
+}
+
+.head .logo {
+ display: block;
+ height: 26px;
+}
+
+.head .left {
+ flex-grow: 1;
+}
+
+.head .left .logo {
+ float: left;
+ margin-top: -20px;
+}
+
+.head .left .logo img {
+ height: 50px;
+}
+
+.head .left .name {
+ color: rgb(251, 191, 36);
+ font-family: "Press Start 2P", sans-serif;
+ font-size: 18px;
+ padding-left: 60px;
+}
+
+.head .right {
+ line-height: 30px;
+ text-align: right;
+}
+
+.head .right a {
+ display: inline-block;
+ margin-right: 15px;
+}
+
+.head .right .social {
+ display: inline-block;
+ font-size: 20px;
+ margin-left: 10px;
+ margin-right: 0;
+}
+
+.body h1 {
+ text-transform: uppercase;
+}
+
+.body p {
+ font-size: 13px;
+ line-height: 26px;
+ margin: 0;
+ padding: 20px 0;
+}
+
+.body .media {
+ margin: auto;
+ max-width: 900px;
+ text-align: center;
+}
+
+.body .media h3 {
+ padding: 60px 0 20px;
+}
+
+.body .media a {
+ display: inline-block;
+ margin: 10px 20px;
+}
+
+.body .media img {
+ height: 70px;
+}
+
+.foot {
+ display: flex;
+ justify-content: center;
+ line-height: 37px;
+ padding: 40px 20px;
+}
+
+.foot .left a {
+ display: block;
+ text-align: right;
+}
+
+.foot .center {
+ padding: 0 80px;
+ text-align: center;
+}
+
+.foot .center h6 {
+ color: rgb(251, 191, 36);
+ font-family: "Press Start 2P", sans-serif;
+ font-size: 16px;
+ margin: 0;
+}
+
+.foot .center img {
+ width: 100px;
+}
+
+.foot .center .social {
+ font-size: 20px;
+ margin: 0 5px;
+}
+
+.foot .right a {
+ display: block;
+}
+
+.notification {
+ border: 1px solid #222222;
+ bottom: 20px;
+ color: #FFFFFF;
+ font-size: 12px;
+ left: 20px;
+ max-width: 375px;
+ padding: 20px 30px;
+ position: fixed;
+ z-index: 10000;
+}
+
+.notification a {
+ color: #FFFFFF;
+ text-decoration: underline;
+}
+
+.notification::before {
+ display: inline-block;
+ font-family: "Font Awesome 5 Free"; font-weight: 900;
+ padding-right: 10px;
+}
+
+.notification.notification-error {
+ background-color: #880000;
+}
+
+.notification.notification-error::before {
+ content: "\f057";
+}
+
+.notification.notification-success {
+ background-color: #008800;
+}
+
+.notification.notification-success::before {
+ content: "\f058";
+}
+
+.btn {
+ display: inline-block;
+ padding: 8px 16px;
+}
+
+.btn-solid,
+.btn-solid:hover {
+ color: #FFFFFF;
+}
+
+.btn-outline {
+ border-style: solid;
+ border-width: 1px;
+}
+
+.btn-solid.btn-success {
+ background-color: #008800;
+}
+
+.btn-outline.btn-success,
+.btn-outline.btn-success:hover {
+ border-color: #008800;
+ color: #008800;
+}
+
+.btn-solid.btn-danger {
+ background-color: #EC131D;
+}
+
+.btn-outline.btn-danger,
+.btn-outline.btn-danger:hover {
+ border-color: #EC131D;
+ color: #EC131D;
+}
+
+@media(max-width: 767px) {
+ .article-banner {
+ margin: 40px 0 20px;
+ padding: 20px 40px;
+ }
+}
+
+@media(max-width: 420px) {
+ .article-banner {
+ padding: 10px 20px;
+ }
+
+ .head {
+ display: block;
+ padding: 10px;
+ }
+
+ .head nav {
+ display: block;
+ text-align: left;
+ }
+
+ .head nav a:first-child{
+ margin-left: 0;
+ }
+
+ .body {
+ padding: 10px;
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..585158b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,21 @@
+{
+ "private": true,
+ "scripts": {
+ "start": "node server/index.js"
+ },
+ "devDependencies": {
+ "@nomiclabs/hardhat-ethers": "2.0.2",
+ "@nomiclabs/hardhat-etherscan": "^2.1.8",
+ "@nomiclabs/hardhat-waffle": "2.0.1",
+ "@openzeppelin/contracts": "4.4.0",
+ "chai": "4.3.4",
+ "dotenv": "10.0.0",
+ "erc721b": "^0.1.5",
+ "ethereum-waffle": "3.4.0",
+ "ethers": "5.4.1",
+ "express": "^4.17.1",
+ "hardhat": "2.4.3",
+ "hardhat-contract-sizer": "2.4.0",
+ "hardhat-gas-reporter": "1.0.6"
+ }
+}
diff --git a/server/index.js b/server/index.js
new file mode 100644
index 0000000..2044a00
--- /dev/null
+++ b/server/index.js
@@ -0,0 +1,10 @@
+const express = require('express')
+const path = require('path')
+const app = express()
+const port = 3000
+
+app.use(express.static(path.resolve(__dirname, '../docs')));
+
+app.listen(port, () => {
+ console.log(`Example app listening at http://localhost:${port}`)
+})
\ No newline at end of file