mirror of
https://github.com/stronk-dev/RandomChad.git
synced 2025-07-05 10:35:08 +02:00
rocketeers now saved in firestore
This commit is contained in:
commit
8a3bedd324
5
.firebaserc
Normal file
5
.firebaserc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"default": "rocketeer-nft"
|
||||||
|
}
|
||||||
|
}
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*
|
||||||
|
node_modules
|
45
functions/.eslintrc.js
Normal file
45
functions/.eslintrc.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
module.exports = {
|
||||||
|
|
||||||
|
// Recommended features
|
||||||
|
"extends": [ "eslint:recommended" ],
|
||||||
|
|
||||||
|
//Parser features
|
||||||
|
parser: "@babel/eslint-parser",
|
||||||
|
parserOptions: {
|
||||||
|
requireConfigFile: false,
|
||||||
|
ecmaVersion: 12,
|
||||||
|
sourceType: "module",
|
||||||
|
ecmaFeatures: {
|
||||||
|
experimentalObjectRestSpread: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Specific rules, 2: err, 1: warn, 0: off
|
||||||
|
rules: {
|
||||||
|
|
||||||
|
"no-case-declarations": 0,
|
||||||
|
"prefer-arrow-callback": 2,
|
||||||
|
"no-mixed-spaces-and-tabs": 1,
|
||||||
|
"no-unused-vars": [ 1, { vars: 'all', args: 'none' } ], // All variables, no function arguments
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// What environment to run in
|
||||||
|
env:{
|
||||||
|
node: true,
|
||||||
|
browser: true,
|
||||||
|
mocha: true,
|
||||||
|
jest: true,
|
||||||
|
es6: true
|
||||||
|
},
|
||||||
|
|
||||||
|
// What global variables should be assumed to exist
|
||||||
|
globals: {
|
||||||
|
context: false,
|
||||||
|
// cy: true,
|
||||||
|
// window: true,
|
||||||
|
// location: true,
|
||||||
|
// fetch: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
functions/.gitignore
vendored
Normal file
1
functions/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
1
functions/.nvmrc
Normal file
1
functions/.nvmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
12
|
6
functions/index.js
Normal file
6
functions/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const functions = require( 'firebase-functions' )
|
||||||
|
const testnetAPI = require( './modules/testnet' )
|
||||||
|
const mainnetAPI = require( './modules/mainnet' )
|
||||||
|
|
||||||
|
exports.testnetMetadata = functions.https.onRequest( testnetAPI )
|
||||||
|
exports.mainnetMetadata = functions.https.onRequest( mainnetAPI )
|
6
functions/modules/express.js
Normal file
6
functions/modules/express.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const express = require( 'express' )
|
||||||
|
const cors = require( 'cors' )
|
||||||
|
|
||||||
|
|
||||||
|
// CORS enabled express generator
|
||||||
|
module.exports = f => express().use( cors( { origin: true } ) )
|
13
functions/modules/firebase.js
Normal file
13
functions/modules/firebase.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Dependencies
|
||||||
|
const admin = require('firebase-admin')
|
||||||
|
|
||||||
|
// Admin api
|
||||||
|
const app = admin.initializeApp()
|
||||||
|
const db = app.firestore()
|
||||||
|
const { FieldValue, FieldPath } = admin.firestore
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
db: db,
|
||||||
|
FieldValue: FieldValue,
|
||||||
|
FieldPath: FieldPath
|
||||||
|
}
|
117
functions/modules/mainnet.js
Normal file
117
functions/modules/mainnet.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
const app = require( './express' )()
|
||||||
|
const name = require( 'random-name' )
|
||||||
|
const { db } = require( './firebase' )
|
||||||
|
|
||||||
|
// ///////////////////////////////
|
||||||
|
// Data sources
|
||||||
|
// ///////////////////////////////
|
||||||
|
const globalAttributes = [
|
||||||
|
{ trait_type: "Age", display_type: "number", values: [
|
||||||
|
{ value: 35, probability: .5 },
|
||||||
|
{ value: 45, probability: .25 },
|
||||||
|
{ value: 25, probability: .25 }
|
||||||
|
] }
|
||||||
|
]
|
||||||
|
const heavenlyBodies = [ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "the Moon", "the Sun" ]
|
||||||
|
const web2domain = 'https://mentor.eth.link/'
|
||||||
|
|
||||||
|
// ///////////////////////////////
|
||||||
|
// Rocketeer helpers
|
||||||
|
// ///////////////////////////////
|
||||||
|
|
||||||
|
// Pick random item from array with equal probability
|
||||||
|
const pickRandomArrayEntry = array => array[ Math.floor( Math.random() * array.length ) ]
|
||||||
|
|
||||||
|
// Pick random attributes based on global attribute array
|
||||||
|
function pickRandomAttributes( attributes ) {
|
||||||
|
|
||||||
|
// Decimal accuracy, if probabilities have the lowest 0.01 then 100 is enough, for 0.001 1000 is needed
|
||||||
|
const probabilityDecimals = 3
|
||||||
|
|
||||||
|
// Remap the trait so it has a 'lottery ticket box' based on probs
|
||||||
|
const attributeLottery = attributes.map( ( { values, ...attribute } ) => ( {
|
||||||
|
// Attribute meta stays the same
|
||||||
|
...attribute,
|
||||||
|
// Values are reduced from objects with probabilities to an array with elements
|
||||||
|
values: values.reduce( ( acc, val ) => {
|
||||||
|
|
||||||
|
const { probability, value } = val
|
||||||
|
|
||||||
|
// Map probabilities to a flat array of items
|
||||||
|
const amountToAdd = 10 * probabilityDecimals * probability
|
||||||
|
for ( let i = 0; i < amountToAdd; i++ ) acc.push( value )
|
||||||
|
return acc
|
||||||
|
|
||||||
|
}, [] )
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
// Pick a random element from the lottery box array items
|
||||||
|
return attributeLottery.map( ( { values, ...attribute } ) => ( {
|
||||||
|
// Attribute meta stays the same
|
||||||
|
...attribute,
|
||||||
|
// Select random entry from array
|
||||||
|
value: pickRandomArrayEntry( values )
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ///////////////////////////////
|
||||||
|
// Specific Rocketeer instances
|
||||||
|
// ///////////////////////////////
|
||||||
|
app.get( '/rocketeer/:id', async ( req, res ) => {
|
||||||
|
|
||||||
|
// Parse the request
|
||||||
|
const { id } = req.params
|
||||||
|
if( !id ) return res.json( { error: `No ID specified in URL` } )
|
||||||
|
|
||||||
|
// Get existing rocketeer if it exists
|
||||||
|
try {
|
||||||
|
|
||||||
|
const oldRocketeer = await db.collection( 'rocketeers' ).doc( id ).get().then( doc => doc.data() )
|
||||||
|
if( oldRocketeer ) return res.json( oldRocketeer )
|
||||||
|
|
||||||
|
} catch( e ) {
|
||||||
|
return res.json( { trace: 'firestore rocketeer read',error: e.message || JSON.stringify( e ) } )
|
||||||
|
}
|
||||||
|
|
||||||
|
// The base object of a new Rocketeer
|
||||||
|
const rocketeer = {
|
||||||
|
name: `${ name.first() } ${ name.middle() } ${ name.last() } of ${ pickRandomArrayEntry( heavenlyBodies ) }`,
|
||||||
|
description: ``,
|
||||||
|
image: ``,
|
||||||
|
external_url: `${ web2domain }rocketeer/${ id }`,
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate randomized attributes
|
||||||
|
rocketeer.attributes = pickRandomAttributes( globalAttributes )
|
||||||
|
|
||||||
|
// TODO: Generate, compile and upload image
|
||||||
|
rocketeer.image = web2domain
|
||||||
|
|
||||||
|
// Save new Rocketeer
|
||||||
|
try {
|
||||||
|
await db.collection( 'rocketeers' ).doc( id ).set( rocketeer )
|
||||||
|
} catch( e ) {
|
||||||
|
return res.json( { trace: 'firestore rocketeer save', error: e.message || JSON.stringify( e ) } )
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the new rocketeer
|
||||||
|
return res.json( rocketeer )
|
||||||
|
|
||||||
|
} )
|
||||||
|
|
||||||
|
|
||||||
|
// ///////////////////////////////
|
||||||
|
// Static collection data
|
||||||
|
// ///////////////////////////////
|
||||||
|
app.get( '/collection', ( req, res ) => res.json( {
|
||||||
|
description: "A testnet collection",
|
||||||
|
external_url: `https://openseacreatures.io/`,
|
||||||
|
image: "https://rocketpool.net/images/rocket.png",
|
||||||
|
name: `Rocketeer collection`,
|
||||||
|
seller_fee_basis_points: 0,
|
||||||
|
fee_recipient: "0x0"
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
module.exports = app
|
26
functions/modules/testnet.js
Normal file
26
functions/modules/testnet.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const app = require( './express' )()
|
||||||
|
|
||||||
|
// Specific Rocketeer instances
|
||||||
|
app.get( '/rocketeer/:id', ( req, res ) => res.json( {
|
||||||
|
description: "A testnet Rocketeer",
|
||||||
|
external_url: `https://openseacreatures.io/${ req.params.id }`,
|
||||||
|
image: "https://rocketpool.net/images/rocket.png",
|
||||||
|
name: `Rocketeer number ${ req.params.id }`,
|
||||||
|
attributes: [
|
||||||
|
{ trait_type: "Occupation", value: "Rocketeer" },
|
||||||
|
{ trait_type: "Age", display_type: "number", value: req.params.id + 42 }
|
||||||
|
]
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
|
||||||
|
// Collection data
|
||||||
|
app.get( '/collection', ( req, res ) => res.json( {
|
||||||
|
description: "A testnet collection",
|
||||||
|
external_url: `https://openseacreatures.io/`,
|
||||||
|
image: "https://rocketpool.net/images/rocket.png",
|
||||||
|
name: `Rocketeer collection`,
|
||||||
|
seller_fee_basis_points: 0,
|
||||||
|
fee_recipient: "0x0"
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
module.exports = app
|
3013
functions/package-lock.json
generated
Normal file
3013
functions/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
functions/package.json
Normal file
31
functions/package.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "functions",
|
||||||
|
"description": "Cloud Functions for Firebase",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"serve": "firebase emulators:start --only functions",
|
||||||
|
"shell": "firebase functions:shell",
|
||||||
|
"start": "npm run shell",
|
||||||
|
"deploy": "firebase deploy --only functions",
|
||||||
|
"logs": "firebase functions:log"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "12"
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"firebase-admin": "^9.12.0",
|
||||||
|
"firebase-functions": "^3.11.0",
|
||||||
|
"random-name": "^0.1.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.15.8",
|
||||||
|
"@babel/eslint-parser": "^7.15.8",
|
||||||
|
"eslint": "^7.6.0",
|
||||||
|
"eslint-config-google": "^0.14.0",
|
||||||
|
"firebase-functions-test": "^0.2.0"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user