├── .prettierignore ├── CONTRIBUTING.md ├── .husky ├── .gitignore └── pre-commit ├── walletToMigrate.txt ├── public ├── emails │ ├── welcome │ │ ├── html.pug │ │ ├── subject.pug │ │ └── text.pug │ └── reset_password │ │ ├── text.pug │ │ ├── subject.pug │ │ └── html.pug ├── 1.png ├── 11.png ├── 111.png ├── 1t.png ├── 2.png ├── 22.png ├── 222.png ├── 2t.png ├── 3.png ├── 33.png ├── 333.png ├── 3t.png ├── 4.png ├── 444.png ├── 4t.png ├── SaTT.png ├── bot1.png ├── bot2.png ├── remix.png ├── compile.png ├── deploy.png ├── icons_ip.png ├── location.png ├── SaTT-noire.png ├── contracts.png ├── keysinfura.png ├── marketcap0.png ├── marketcap1.png ├── moonboy12.png ├── createinfura.png ├── dateRequest.png ├── default_cover.png ├── reject-link.png ├── satt-logo12.png ├── changeEmail-bg.png ├── facebook-icone.png ├── code_change_email.png ├── emailtemplate │ ├── satt-connect.html │ ├── create-tron-wallet.html │ ├── email_validated_keystore_code.html │ ├── email_validated_code.html │ ├── contact_support.html │ └── Email_Template_link_added.html ├── campaign.json ├── copy.svg ├── js │ └── ui.js ├── tron-icon.svg ├── locales │ ├── en.json │ └── fr.json └── privacy.html ├── .prettierrc.json ├── libs └── transfer │ ├── package-lock.json │ ├── index.js │ ├── config.js │ ├── package.json │ ├── transfer-TRON.js │ ├── transfer-btc.js │ ├── readme.md │ └── transfer-tokens.js ├── .github ├── ISSUE_TEMPLATE │ ├── something-else.md │ ├── config.yml │ ├── feature-request.yaml │ └── bug-report.yaml └── workflows │ └── codeql.yml ├── .idea ├── vcs.xml ├── misc.xml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml ├── satt-backend.iml └── runConfigurations.xml ├── model ├── walletUserNode.model.js ├── interests.model.js ├── captcha.model.js ├── event.model.js ├── customToken.model.js ├── request.model.js ├── tikTokProfile.model.js ├── fbPage.model.js ├── userExternalWallet.model.js.js ├── notification.model.js ├── linkedinProfile.model.js ├── googleProfile.model.js ├── fbProfile.model.js ├── index.js ├── campaignLink.model.js ├── campaigns.model.js ├── wallet.model.js ├── UserArchive.model.js ├── user.model.js └── twitterProfile.model.js ├── web3 ├── verifySignature.js ├── account.js ├── oracles.js ├── utils.js ├── web3-connection.js └── graph.js ├── conf ├── wallets │ ├── campaign.tron.json │ ├── campaign.polygon.json │ ├── bep20.json │ └── campaign.json ├── database.js ├── corsSetup.js ├── swaggerSetup.js ├── privkey.pem ├── ssl │ ├── privkey.pem │ └── fullchain.pem └── fullchain.pem ├── ecosystem.config.js ├── helpers └── response-handler.js ├── changepackage.js ├── middleware ├── errorHandler.middleware.js ├── verifySignature.middleware.js ├── authValidator.middleware.js └── profileValidator.middleware.js ├── LICENCE.md ├── route-setup └── routeSetup.js ├── app.js ├── .gitignore ├── bin └── www ├── manager ├── notification.js └── accounts.js ├── contracts ├── PriceGap.sol ├── SattResolver.sol └── oracle.sol ├── routes └── external.routes.js └── package.json /.prettierignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /walletToMigrate.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/emails/welcome/html.pug: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/emails/welcome/subject.pug: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/emails/welcome/text.pug: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/emails/reset_password/text.pug: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/emails/reset_password/subject.pug: -------------------------------------------------------------------------------- 1 | = 'Password recovry' 2 | -------------------------------------------------------------------------------- /public/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/1.png -------------------------------------------------------------------------------- /public/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/11.png -------------------------------------------------------------------------------- /public/111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/111.png -------------------------------------------------------------------------------- /public/1t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/1t.png -------------------------------------------------------------------------------- /public/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/2.png -------------------------------------------------------------------------------- /public/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/22.png -------------------------------------------------------------------------------- /public/222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/222.png -------------------------------------------------------------------------------- /public/2t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/2t.png -------------------------------------------------------------------------------- /public/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/3.png -------------------------------------------------------------------------------- /public/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/33.png -------------------------------------------------------------------------------- /public/333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/333.png -------------------------------------------------------------------------------- /public/3t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/3t.png -------------------------------------------------------------------------------- /public/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/4.png -------------------------------------------------------------------------------- /public/444.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/444.png -------------------------------------------------------------------------------- /public/4t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/4t.png -------------------------------------------------------------------------------- /public/SaTT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/SaTT.png -------------------------------------------------------------------------------- /public/bot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/bot1.png -------------------------------------------------------------------------------- /public/bot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/bot2.png -------------------------------------------------------------------------------- /public/remix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/remix.png -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /public/compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/compile.png -------------------------------------------------------------------------------- /public/deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/deploy.png -------------------------------------------------------------------------------- /public/icons_ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/icons_ip.png -------------------------------------------------------------------------------- /public/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/location.png -------------------------------------------------------------------------------- /public/SaTT-noire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/SaTT-noire.png -------------------------------------------------------------------------------- /public/contracts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/contracts.png -------------------------------------------------------------------------------- /public/keysinfura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/keysinfura.png -------------------------------------------------------------------------------- /public/marketcap0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/marketcap0.png -------------------------------------------------------------------------------- /public/marketcap1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/marketcap1.png -------------------------------------------------------------------------------- /public/moonboy12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/moonboy12.png -------------------------------------------------------------------------------- /public/createinfura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/createinfura.png -------------------------------------------------------------------------------- /public/dateRequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/dateRequest.png -------------------------------------------------------------------------------- /public/default_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/default_cover.png -------------------------------------------------------------------------------- /public/reject-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/reject-link.png -------------------------------------------------------------------------------- /public/satt-logo12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/satt-logo12.png -------------------------------------------------------------------------------- /public/changeEmail-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/changeEmail-bg.png -------------------------------------------------------------------------------- /public/facebook-icone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/facebook-icone.png -------------------------------------------------------------------------------- /public/code_change_email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaTT-Wallet/Backend/HEAD/public/code_change_email.png -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": false, 5 | "singleQuote": true 6 | } -------------------------------------------------------------------------------- /libs/transfer/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atayen-org/transfer", 3 | "version": "2.3.6", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/something-else.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Something Else 3 | about: Tell us something else 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Support 4 | url: https://t.me/sattdevelopers 5 | about: Please ask questions and discuss here 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /libs/transfer/index.js: -------------------------------------------------------------------------------- 1 | const { transferTokens } = require('./transfer-tokens') 2 | const { transferBTC } = require('./transfer-btc') 3 | 4 | module.exports = { 5 | transferTokens, 6 | transferBTC, 7 | } 8 | -------------------------------------------------------------------------------- /libs/transfer/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | BTC_CMD: 3 | './bin/bitcoin-cli -rpcconnect=192.168.0.23 -rpcuser=btcuser -rpcpassword=BtcUs3R**-a ', 4 | BTS_FEES: 'https://bitcoinfees.earn.com/api/v1/fees/recommended', 5 | } 6 | -------------------------------------------------------------------------------- /model/walletUserNode.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const walletUserSchema = mongoose.Schema({ 4 | idUser: { type: Number, required: true, ref: 'user' }, 5 | wallet: { type: String }, 6 | }) 7 | 8 | const WalletUserNode = mongoose.model('wallet_user_node', walletUserSchema) 9 | -------------------------------------------------------------------------------- /public/emails/reset_password/html.pug: -------------------------------------------------------------------------------- 1 | h1 Hello #{firstName} #{lastName} 2 | p. 3 | Welcome to My App! Now your test emails will be safe. We just need to make sure your account is real. 4 | Please, click the button below and start using your account. 5 | a(href='https://example.com/confirmation') Confirm! 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /model/interests.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | const interestsSchema = mongoose.Schema( 3 | { 4 | interests: [{ type: String }], 5 | userId: { type: Number }, 6 | }, 7 | { collection: 'interests' } 8 | ) 9 | 10 | const Interests = mongoose.model('interests', interestsSchema) 11 | module.exports = Interests 12 | -------------------------------------------------------------------------------- /.idea/satt-backend.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /model/captcha.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const captchaSchema = mongoose.Schema( 4 | { 5 | originalImage: { type: String }, 6 | puzzle: { type: String }, 7 | position: { type: Number }, 8 | }, 9 | { collection: 'captcha' } 10 | ) 11 | const Captcha = mongoose.model('captcha', captchaSchema) 12 | module.exports = Captcha 13 | -------------------------------------------------------------------------------- /public/emailtemplate/satt-connect.html: -------------------------------------------------------------------------------- 1 |

Satt Connect

2 | 3 |
4 |
5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /web3/verifySignature.js: -------------------------------------------------------------------------------- 1 | const { utils } = require('ethers'); 2 | 3 | const verifySignature = (message, signature, address) => { 4 | const messageHash = utils.hashMessage(message); 5 | const recoveredAddress = utils.recoverAddress(messageHash, signature); 6 | return utils.isAddress(address) && address.toLowerCase() === recoveredAddress.toLowerCase(); 7 | } 8 | 9 | module.exports = verifySignature; -------------------------------------------------------------------------------- /web3/account.js: -------------------------------------------------------------------------------- 1 | const { web3 } = require('./web3-connection') 2 | 3 | const getBalanceOf = function (address) { 4 | return web3.eth.getBalance(address) 5 | } 6 | 7 | const unlockAccount = async function ({ web3, keyStore, walletPassword }) { 8 | return web3.eth.accounts.wallet.decrypt([keyStore], walletPassword) 9 | } 10 | 11 | module.exports = { 12 | getBalanceOf, 13 | unlockAccount, 14 | } 15 | -------------------------------------------------------------------------------- /libs/transfer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atayen-org/transfer", 3 | "version": "2.3.9", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/SaTT-Wallet/Backend/tree/mainnet/libs/transfer" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /conf/wallets/campaign.tron.json: -------------------------------------------------------------------------------- 1 | {"address":"41139528ff42ef872f8c3e1b729cb1966fb4bddef0","id":"d299a361-8851-465d-9fce-35e44a38dec9","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"c0afe8c1d4cfe486bcc0b05813656687"},"ciphertext":"1d6d47856cc84eaba94cde604260c1f0378a06b0cc2a17fa2e39d36f7fedffd4","kdf":"scrypt","kdfparams":{"salt":"e2f054a4d2a3e11bad08d6765b2b75e7d8ae5613f79ec85a35ea99a495c3248c","n":131072,"dklen":32,"p":1,"r":8},"mac":"b8a27a27eb2b716e16cc7ed66b3e98df5e6cb53744e33548000aa5f06ece0096"}} -------------------------------------------------------------------------------- /ecosystem.config.js: -------------------------------------------------------------------------------- 1 | const packagejson = require('./package.json') 2 | 3 | module.exports = { 4 | apps: [ 5 | { 6 | name: packagejson.name, 7 | script: './bin/www', 8 | env: { 9 | NODE_ENV: 'local', 10 | }, 11 | env_testnet: { 12 | NODE_ENV: 'testnet', 13 | }, 14 | env_mainnet: { 15 | NODE_ENV: 'mainnet', 16 | max_memory_restart: '900M', 17 | }, 18 | }, 19 | ], 20 | } 21 | -------------------------------------------------------------------------------- /model/event.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const eventSchema = mongoose.Schema( 4 | { 5 | id: { type: String }, 6 | prom: { type: String }, 7 | type: { type: String }, 8 | date: { type: Number }, 9 | txhash: { type: String }, 10 | contract: { type: String }, 11 | owner: { type: String }, 12 | media_url: { type: String }, 13 | }, 14 | { timestamps: true, strict: false, collection: 'event' } 15 | ) 16 | 17 | const Event = mongoose.model('event', eventSchema) 18 | module.exports = Event 19 | -------------------------------------------------------------------------------- /helpers/response-handler.js: -------------------------------------------------------------------------------- 1 | class responseHandler { 2 | constructor() {} 3 | 4 | makeResponseData = (res, code, message, data = null, id = false) => { 5 | return res.status(code).send({ 6 | code, 7 | message, 8 | data, 9 | ...(id && { id }), 10 | }) 11 | } 12 | makeResponseError = (res, code, error) => { 13 | if (!res.status) return 14 | return res.status(code).send({ 15 | code, 16 | error, 17 | }) 18 | } 19 | } 20 | 21 | module.exports.responseHandler = new responseHandler() 22 | -------------------------------------------------------------------------------- /model/customToken.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const customTokenSchema = mongoose.Schema( 4 | { 5 | tokenAdress: { type: String }, 6 | decimal: { type: Number }, 7 | symbol: { type: String }, 8 | network: { type: String }, 9 | picUrl: { type: String }, 10 | tokenName: { type: String }, 11 | sn_users: [{ type: Number, required: true, ref: 'user' }], 12 | }, 13 | { 14 | collection: 'custom_token', 15 | } 16 | ) 17 | 18 | const CustomToken = mongoose.model('custom_token', customTokenSchema) 19 | 20 | module.exports = CustomToken 21 | -------------------------------------------------------------------------------- /web3/oracles.js: -------------------------------------------------------------------------------- 1 | exports.limitStats = (typeSN, stats, ratios, abos, limit = '') => { 2 | if (!limit) { 3 | var limits = ratios[4] 4 | limit = limits[parseInt(typeSN) - 1] 5 | } 6 | if (limit > 0) { 7 | limit = parseFloat(limit) 8 | var max = Math.ceil((limit * parseFloat(abos)) / 100) 9 | if (+stats.views > max) { 10 | stats.views = max 11 | } 12 | if (+stats.likes > max) { 13 | stats.likes = max 14 | } 15 | if (+stats.shares > max) { 16 | stats.shares = max 17 | } 18 | } 19 | 20 | return stats 21 | } 22 | -------------------------------------------------------------------------------- /web3/utils.js: -------------------------------------------------------------------------------- 1 | const { web3 } = require('./web3-connection') 2 | const { Constants } = require('../conf/const') 3 | 4 | const isValidAddress = function (address) { 5 | return web3.eth.isValidAddress(address) 6 | } 7 | 8 | const getGasPrice = function () {} 9 | 10 | const getBalanceOf = function () {} 11 | 12 | const estimateGas = function () {} 13 | 14 | const getWallet = function () {} 15 | 16 | const getContractByTokenAddress = function (web3, contractAddress) { 17 | return new web3.eth.Contract(Constants.token.abi, contractAddress) 18 | } 19 | 20 | module.exports = { 21 | getContractByTokenAddress, 22 | isValidAddress, 23 | } 24 | -------------------------------------------------------------------------------- /model/request.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const requestSchema = mongoose.Schema( 4 | { 5 | id: { type: String }, 6 | typeSN: { type: Number }, 7 | idUser: { type: String }, 8 | idPost: { type: String }, 9 | new: { type: Boolean, default: true }, 10 | date: { type: Number }, 11 | likes: { type: Number, default: 0 }, 12 | shares: { type: Number, default: 0 }, 13 | views: { type: Number, default: 0 }, 14 | }, 15 | { 16 | collection: 'request', 17 | } 18 | ) 19 | 20 | const Request = mongoose.model('request', requestSchema) 21 | module.exports = Request 22 | -------------------------------------------------------------------------------- /conf/database.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { mongoConnection } = require('./config') 3 | require('dotenv').config() 4 | exports.connect = () => { 5 | mongoose.connect( 6 | mongoConnection(), 7 | { 8 | useNewUrlParser: true, 9 | useUnifiedTopology: true, 10 | useCreateIndex: true, 11 | useFindAndModify: false, 12 | } 13 | ).then(() => { 14 | if(process.env.NODE_ENV != "mainnet") console.log('******connection establed to MongoServer*******') 15 | }).catch((err) => { 16 | if(process.env.NODE_ENV != "mainnet") console.log('Failed to connect to MongoDB', err) 17 | }) 18 | } -------------------------------------------------------------------------------- /model/tikTokProfile.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const tikTokProfileSchema = mongoose.Schema( 4 | { 5 | accessToken: { type: String }, 6 | refreshToken: { type: String }, 7 | userId: { type: Number, required: true, ref: 'user' }, 8 | userTiktokId: { type: String }, 9 | username: { type: String }, 10 | displayName: { type: String }, 11 | profileImage: { type: String }, 12 | followers: Number, 13 | }, 14 | 15 | { 16 | collection: 'tikTok_profile', 17 | } 18 | ) 19 | const TikTokProfile = mongoose.model('tikTok_profile', tikTokProfileSchema) 20 | module.exports = TikTokProfile 21 | -------------------------------------------------------------------------------- /conf/wallets/campaign.polygon.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "8a6cc367-db49-4fb4-a46b-2a5dd50c90d7", 4 | "address": "d01a19594444e179f2b27faff73907508fc96d1b", 5 | "crypto": { 6 | "ciphertext": "1c212f452f78ae0c1c1c9ee199923a4abbf92ff0790ef1054ecb87388c15818c", 7 | "cipherparams": { 8 | "iv": "e68d9ac516c239e6f40da4b35152d610" 9 | }, 10 | "cipher": "aes-128-ctr", 11 | "kdf": "scrypt", 12 | "kdfparams": { 13 | "dklen": 32, 14 | "salt": "839688c2298c829239b0c2fc5a66edd0b3369700655a9afeb8b62764aa7965fe", 15 | "n": 8192, 16 | "r": 8, 17 | "p": 1 18 | }, 19 | "mac": "f96ff770a448732ff6abee63caefd3e93ce88c79b3a9d31e74d2d49029f13639" 20 | } 21 | } -------------------------------------------------------------------------------- /public/campaign.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "30e6ef6c-80f7-4e24-b09a-3fa14c1c8eea", 4 | "address": "68dd0c4c13432fa9ee3b9fb3420c3899cd75f873", 5 | "crypto": { 6 | "ciphertext": "8f72e511783cee321aa08d7a17e773672bf1ee5a39472987165863d81d965ae6", 7 | "cipherparams": { "iv": "5ec39e7418dda07a43b64780a1aca4a5" }, 8 | "cipher": "aes-128-ctr", 9 | "kdf": "scrypt", 10 | "kdfparams": { 11 | "dklen": 32, 12 | "salt": "1a089e096cd8714639ed662ec3ebeef9d4d86dfb8dc76b63b980de2cc5c5b7a1", 13 | "n": 8192, 14 | "r": 8, 15 | "p": 1 16 | }, 17 | "mac": "10a2e8a57252a8f33eda472738ab24c324fe1b5bf689be0dee0807e27ccd55ab" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /changepackage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const fileName = './package.json' 3 | const file = require(fileName) 4 | let version = file.version.split('.') 5 | var myArgs = process.argv.slice(2) 6 | 7 | if (!myArgs[0] || myArgs[0] === 'developement') { 8 | version[2] = parseInt(version[2]) + 1 9 | } 10 | if (myArgs[0] === 'qa') { 11 | version[2] = 0 12 | version[1] = parseInt(version[1]) + 1 13 | } 14 | 15 | if (myArgs[0] === 'prod') { 16 | version[2] = 0 17 | version[1] = 0 18 | version[0] = parseInt(version[0]) + 1 19 | } 20 | 21 | file.version = version[0] + '.' + version[1] + '.' + version[2] 22 | 23 | fs.writeFile(fileName, JSON.stringify(file, null, 4), function writeJSON(err) { 24 | if (err) return console.log(err) 25 | }) 26 | -------------------------------------------------------------------------------- /conf/wallets/bep20.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "8a6cc367-db49-4fb4-a46b-2a5dd50c90d7", 4 | "address": "d01a19594444e179f2b27faff73907508fc96d1b", 5 | "crypto": { 6 | "ciphertext": "1c212f452f78ae0c1c1c9ee199923a4abbf92ff0790ef1054ecb87388c15818c", 7 | "cipherparams": { 8 | "iv": "e68d9ac516c239e6f40da4b35152d610" 9 | }, 10 | "cipher": "aes-128-ctr", 11 | "kdf": "scrypt", 12 | "kdfparams": { 13 | "dklen": 32, 14 | "salt": "839688c2298c829239b0c2fc5a66edd0b3369700655a9afeb8b62764aa7965fe", 15 | "n": 8192, 16 | "r": 8, 17 | "p": 1 18 | }, 19 | "mac": "f96ff770a448732ff6abee63caefd3e93ce88c79b3a9d31e74d2d49029f13639" 20 | } 21 | } -------------------------------------------------------------------------------- /conf/wallets/campaign.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "19945a1e-e7f1-4a4e-bb45-c08cb2c40acb", 4 | "address": "64a453a062985cd56fc685c0ec9d820ef8460976", 5 | "crypto": { 6 | "ciphertext": "3cf0276f8b69d9600eb1c4853baf76301c56077590c8f25a37d72c1ec26fa0e2", 7 | "cipherparams": { "iv": "3feb7943c5057e4bcbc007183ad70c9c" }, 8 | "cipher": "aes-128-ctr", 9 | "kdf": "scrypt", 10 | "kdfparams": { 11 | "n": 8192, 12 | "r": 8, 13 | "p": 1, 14 | "dklen": 32, 15 | "salt": "68761f574d125aa5ddce2dbcbe7df17b2af8b5f03d942ec7ea2078a6751fe870" 16 | }, 17 | "mac": "fc3bde4105da7fb4bc82c5e87adacb8e7a8c37b4b07e85382a3af41b773b18cd" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /model/fbPage.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const fbPageSchema = mongoose.Schema( 4 | { 5 | UserId: { type: Number, required: true, ref: 'user' }, 6 | id: { type: String }, 7 | instagram_id: { type: String }, 8 | threads_id : String, 9 | threads_picture : String, 10 | threads_followers : Number, 11 | instagram_username: { type: String }, 12 | name: { type: String }, 13 | picture: { type: String }, 14 | subscribers: { type: Number }, 15 | token: { type: String }, 16 | username: { type: String }, 17 | }, 18 | { collection: 'fb_page' } 19 | ) 20 | 21 | const FbPage = mongoose.model('fb_page', fbPageSchema) 22 | module.exports = FbPage 23 | -------------------------------------------------------------------------------- /model/userExternalWallet.model.js.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const { mongoConnection } = require('../conf/config'); 3 | const db = mongoose.createConnection(mongoConnection(), { 4 | useNewUrlParser: true, 5 | useUnifiedTopology: true, 6 | useCreateIndex: true, 7 | useFindAndModify: false, 8 | }); 9 | 10 | const userExternalWalletSchema = new mongoose.Schema({ 11 | UserId: { 12 | type: Number, 13 | required: true, 14 | unique:true 15 | }, 16 | walletId: { 17 | type: String, 18 | required: true, 19 | }, 20 | balance: { 21 | type: Number, 22 | default: 0, 23 | }, 24 | }); 25 | 26 | const UserExternalWallet = db.model('UserExternalWallet', userExternalWalletSchema); 27 | 28 | module.exports = UserExternalWallet; -------------------------------------------------------------------------------- /model/notification.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const notificationSchema = mongoose.Schema( 4 | { 5 | idNode: { type: String }, 6 | type: { type: String }, 7 | status: { type: String }, 8 | label: { 9 | // type: { type: String }, 10 | // cmp_name: { type: String }, 11 | // cmp_hash: { type: String }, 12 | // linkHash: { type: String }, 13 | }, 14 | isSeen: { type: Boolean }, 15 | isSend: { type: Boolean }, 16 | attachedEls: { 17 | id: { type: Number }, 18 | }, 19 | }, 20 | { timestamps: true, collection: 'notification' } 21 | ) 22 | 23 | const Notification = mongoose.model('notification', notificationSchema) 24 | module.exports = Notification 25 | -------------------------------------------------------------------------------- /public/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /middleware/errorHandler.middleware.js: -------------------------------------------------------------------------------- 1 | const handleEndpointNotFound = (req, res) => { 2 | res.status(404).format({ 3 | json() { 4 | res.json({error: 'Not found'}) 5 | }, 6 | default() { 7 | res.type('txt').send('Not found') 8 | } 9 | }) 10 | } 11 | 12 | 13 | const errorHandler = (err, req, res, next) => { 14 | if(err) { 15 | const status = err.status || 500; 16 | const message = err.message || 'An error occurred during the request.' 17 | const name = err.name || 'Error' 18 | const body = { 19 | name, 20 | message, 21 | status 22 | } 23 | if(process.env.NODE_ENV != "mainnet") console.error('error : ', message); 24 | // render the error page 25 | res.status(status).json(body); 26 | 27 | } else next(); 28 | } 29 | 30 | 31 | 32 | module.exports = {errorHandler, handleEndpointNotFound}; -------------------------------------------------------------------------------- /model/linkedinProfile.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const linkedinProfileSchema = mongoose.Schema( 4 | { 5 | accessToken: { type: String }, 6 | userId: { type: Number, required: true, ref: 'user' }, 7 | linkedinId: { type: String, required : true}, 8 | pages: [ 9 | { 10 | 'organization~': { 11 | localizedName: { type: String }, 12 | }, 13 | role: { type: String }, 14 | organization: { type: String }, 15 | roleAssignee: { type: String }, 16 | state: { type: String }, 17 | subscribers: { type: Number }, 18 | photo: { type: String }, 19 | }, 20 | ], 21 | refreshToken: { type: String }, 22 | }, 23 | 24 | { 25 | collection: 'linkedin_profile', 26 | } 27 | ) 28 | 29 | const LinkedinProfile = mongoose.model( 30 | 'linkedin_profile', 31 | linkedinProfileSchema 32 | ) 33 | module.exports = LinkedinProfile 34 | -------------------------------------------------------------------------------- /public/js/ui.js: -------------------------------------------------------------------------------- 1 | $(document).ready(() => { 2 | var form = document.getElementById('inspect-form') 3 | var input = document.getElementById('url') 4 | var inspect = document.getElementById('') 5 | 6 | function onSubmit() { 7 | var url = input.value 8 | var query 9 | if (url.indexOf('https://www.facebook.com/') != -1) { 10 | query = '/facebook?url=' + url 11 | } 12 | if (url.indexOf('https://twitter.com/') != -1) { 13 | var parts = url.split('/') 14 | query = '/twitter/' + parts[3] + '/' + parts[5] 15 | } 16 | if (url.indexOf('https://www.instagram.com/') != -1) { 17 | var parts = url.split('/') 18 | query = '/instagram/' + parts[4] 19 | } 20 | if (url.indexOf('https://www.youtube.com/watch') != -1) { 21 | var parts = url.split('=') 22 | query = '/youtube/' + parts[1] 23 | } 24 | $.get(query, function (data) { 25 | $('#result').html(data) 26 | }) 27 | return false 28 | } 29 | 30 | $('#inspect').on('click', onSubmit) 31 | }) 32 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 SaTT Wallet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /conf/corsSetup.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const corsSetup = (req, res, next) => { 3 | const apiKey = req.headers['api-key']; 4 | 5 | if (apiKey && apiKey === process.env.API_KEY) { 6 | return next(); 7 | } 8 | 9 | if (process.env.NODE_ENV === "mainnet") { 10 | const allowedOrigins = [ 11 | 'https://dapp.satt.com', 12 | 'https://satt-token.com', 13 | 'https://app.ihave.io', 14 | 'http://backoffice.atayen.us', 15 | 'https://app.satt.com' 16 | ]; 17 | 18 | if (req.headers.origin && allowedOrigins.includes(req.headers.origin)) { 19 | return next(); 20 | } 21 | 22 | const blockedUrls = [ 23 | 'google', 24 | 'youtube', 25 | 'facebook', 26 | 'tikTok', 27 | 'tiktok', 28 | 'linkedin', 29 | 'twitter', 30 | 'telegram' 31 | ]; 32 | 33 | if (blockedUrls.some(url => req.url.includes(url))) { 34 | return next(); 35 | } 36 | 37 | return res.redirect("https://satt-token.com"); 38 | } 39 | 40 | return next(); 41 | }; 42 | 43 | 44 | 45 | module.exports = corsSetup -------------------------------------------------------------------------------- /route-setup/routeSetup.js: -------------------------------------------------------------------------------- 1 | const loginRoutes = require('../routes/login.routes') 2 | const walletRoutes = require('../routes/wallet.routes') 3 | const profileRoutes = require('../routes/profile.routes') 4 | const campaignRoutes = require('../routes/campaign.routes') 5 | const externalRoutes = require('../routes/external.routes') 6 | const {swaggerUi, swaggerSpec, cssOptions} = require('../conf/swaggerSetup'); 7 | const {errorHandler, handleEndpointNotFound} = require('../middleware/errorHandler.middleware'); 8 | 9 | const setupRoutes = (app) => { 10 | 11 | // AUTH ROUTES 12 | app.use('/auth', loginRoutes); 13 | 14 | // WALLET ROUTES 15 | app.use('/wallet', walletRoutes); 16 | 17 | // PROFILE ROUTES 18 | app.use('/profile', profileRoutes); 19 | 20 | // CAPAIGN ROUTES 21 | app.use('/campaign', campaignRoutes); 22 | 23 | // EXTERNAL ROUTES FOR DAPP 24 | app.use('/external', externalRoutes) 25 | 26 | // SWAGGER DOCS 27 | app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, cssOptions)); 28 | 29 | // CATCH NOT FOUND END-POINTS 30 | app.use(handleEndpointNotFound) 31 | 32 | // ERROR HANDLER 33 | app.use(errorHandler) 34 | 35 | } 36 | 37 | 38 | 39 | 40 | module.exports = setupRoutes; -------------------------------------------------------------------------------- /model/googleProfile.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const googleProfileSchema = mongoose.Schema( 4 | { 5 | refreshToken: { type: String }, 6 | accessToken: { type: String }, 7 | UserId: { type: Number, required: true, ref: 'user' }, 8 | google_id: { type: String }, 9 | channelTitle: { type: String }, 10 | channelImage: { 11 | default: { 12 | url: { type: String }, 13 | width: { type: Number }, 14 | height: { type: Number }, 15 | }, 16 | medium: { 17 | url: { type: String }, 18 | width: { type: Number }, 19 | height: { type: Number }, 20 | }, 21 | high: { 22 | url: { type: String }, 23 | width: { type: Number }, 24 | height: { type: Number }, 25 | }, 26 | }, 27 | channelStatistics: { 28 | viewCount: { type: Number }, 29 | subscriberCount: { type: Number }, 30 | hiddenSubscriberCount: { type: Boolean }, 31 | videoCount: { type: Number }, 32 | }, 33 | channelId: { type: String }, 34 | }, 35 | { 36 | collection: 'google_profile', 37 | } 38 | ) 39 | 40 | const GoogleProfile = mongoose.model('google_profile', googleProfileSchema) 41 | module.exports = GoogleProfile 42 | -------------------------------------------------------------------------------- /model/fbProfile.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const fbProfileSchema = mongoose.Schema( 4 | { 5 | id: { type: String }, 6 | username: { type: String }, 7 | displayName: { type: String }, 8 | name: { 9 | familyName: { type: String }, 10 | givenName: { type: String }, 11 | middleName: { type: String }, 12 | }, 13 | gender: { type: String }, 14 | profileUrl: { type: String }, 15 | photos: [ 16 | { 17 | value: { type: String }, 18 | }, 19 | ], 20 | provider: { type: String }, 21 | _raw: { type: String }, 22 | _json: { 23 | id: { type: String }, 24 | name: { type: String }, 25 | picture: { 26 | data: { 27 | height: { type: Number }, 28 | is_silhouette: { type: Boolean }, 29 | url: { type: String }, 30 | width: { type: Number }, 31 | }, 32 | }, 33 | token_for_business: { type: String }, 34 | }, 35 | accessToken: { type: String }, 36 | UserId: { type: Number, required: true, ref: 'user' }, 37 | }, 38 | { 39 | collection: 'fb_profile', 40 | } 41 | ) 42 | 43 | const FbProfile = mongoose.model('fb_profile', fbProfileSchema) 44 | module.exports = FbProfile 45 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const helmet = require('helmet'); 3 | const mongoSanitize = require('express-mongo-sanitize'); 4 | const cors = require('cors'); 5 | const corsSetup = require('./conf/corsSetup'); 6 | const setupRoutes = require('./route-setup/routeSetup'); 7 | const logger = require('morgan'); 8 | const cookieParser = require('cookie-parser'); 9 | const path = require('path'); 10 | const { connect } = require('./conf/database'); 11 | require('dotenv').config({ 12 | path: `.env.${process.env.NODE_ENV}` 13 | }); 14 | 15 | const app = express(); 16 | // Middleware 17 | app.use(express.json({ limit: '50mb', extended: true })); 18 | app.use(express.urlencoded({ limit: '50mb', extended: true, parameterLimit: 50000 })); 19 | app.use(mongoSanitize({ 20 | allowDots: true, 21 | replaceWith: '_', 22 | })); 23 | 24 | // Security 25 | app.disable('x-powered-by'); 26 | app.use(helmet()); 27 | app.use(helmet.frameguard({ action: 'deny' })); 28 | 29 | // Cross-origin resource sharing 30 | app.use(cors('*')); 31 | app.use(corsSetup); 32 | 33 | // Logging 34 | app.use(logger('combined')); 35 | 36 | // Cookie parsing 37 | app.use(cookieParser()); 38 | 39 | // Static files 40 | app.use(express.static(path.join(__dirname, 'public'))); 41 | app.use('/assets', express.static('public')); 42 | 43 | // View engine 44 | app.set('view engine', 'ejs'); 45 | 46 | // Connect to database 47 | connect(); 48 | 49 | // Setup routes 50 | setupRoutes(app); 51 | 52 | module.exports = app; 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yaml: -------------------------------------------------------------------------------- 1 | name: 💡 Feature Request 2 | description: Share your amazing ideas! 3 | title: '[Feature Request] ' 4 | labels: [Feature Request, Triage] 5 | assignees: 6 | - Chef-Cheems 7 | - chef-jojo 8 | body: 9 | - type: checkboxes 10 | attributes: 11 | label: Is there an existing issue for this? 12 | description: Please search to see if an issue already exists for the feature you requested. 13 | options: 14 | - label: I have searched the existing issues 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: Is your feature request related to a problem you are facing? 19 | description: Enter a clear and concise description of what the problem is 20 | placeholder: I'm always frustrated when [...] 21 | validations: 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: Describe the solution you'd like 26 | description: A clear and concise description of what you want to happen. 27 | validations: 28 | required: true 29 | - type: textarea 30 | attributes: 31 | label: How does this feature benefit SATT-TOKEN users and SATT holders? 32 | description: Explain how this feature will be beneficial for the SATT-TOKEN community and ecosystem. 33 | validations: 34 | required: true 35 | - type: textarea 36 | attributes: 37 | label: Anything else? 38 | description: Add any other context or screenshots about the feature request here. 39 | -------------------------------------------------------------------------------- /model/index.js: -------------------------------------------------------------------------------- 1 | const User = require('../model/user.model') 2 | const GoogleProfile = require('../model/googleProfile.model') 3 | const FbProfile = require('../model/fbProfile.model') 4 | const LinkedinProfile = require('../model/linkedinProfile.model') 5 | const TikTokProfile = require('../model/tikTokProfile.model') 6 | const Interests = require('../model/interests.model') 7 | const TwitterProfile = require('../model/twitterProfile.model') 8 | const Notification = require('../model/notification.model') 9 | const FbPage = require('../model/fbPage.model') 10 | const Wallet = require('../model/wallet.model') 11 | const CustomToken = require('../model/customToken.model') 12 | const CampaignLink = require('../model/campaignLink.model') 13 | var Campaigns = require('../model/campaigns.model') 14 | var Event = require('../model/event.model') 15 | var Request = require('../model/request.model') 16 | var Captcha = require('../model/captcha.model') 17 | var UserArchived = require('../model/UserArchive.model') 18 | const WalletUserNode = require('../model/walletUserNode.model') 19 | const UserExternalWallet = require('../model/userExternalWallet.model.js'); 20 | 21 | module.exports = { 22 | UserArchived, 23 | Campaigns, 24 | Captcha, 25 | Request, 26 | Event, 27 | CampaignLink, 28 | Campaigns, 29 | User, 30 | GoogleProfile, 31 | FbProfile, 32 | LinkedinProfile, 33 | TikTokProfile, 34 | Interests, 35 | TwitterProfile, 36 | Notification, 37 | FbPage, 38 | Wallet, 39 | CustomToken, 40 | WalletUserNode, 41 | UserExternalWallet 42 | } -------------------------------------------------------------------------------- /conf/swaggerSetup.js: -------------------------------------------------------------------------------- 1 | const swaggerUi = require('swagger-ui-express') 2 | const swaggerJSDoc = require('swagger-jsdoc') 3 | const package = require('./../package.json') 4 | require('dotenv').config() 5 | let host 6 | if (process.env.NODE_ENV == 'testnet') { 7 | host = process.env.BASEURL 8 | } else if (process.env.NODE_ENV == 'local') { 9 | host = process.env.BASEURLLOCAL 10 | } else { 11 | host = process.env.BASEURL_MAINNET 12 | } 13 | const swaggerDefinition = { 14 | openapi: '3.0.0', 15 | info: { 16 | title: 'API for node-satt', 17 | version: package.version, 18 | description: 19 | 'Welcome to SaTT Webservice endpoint, this backend provides webservice to SaTT WebWallet and advertising campaign manager', 20 | customCss: '.swagger-ui .topbar { display: none }', 21 | }, 22 | host: host, 23 | components: { 24 | securitySchemes: { 25 | bearerAuth: { 26 | type: 'http', 27 | scheme: 'bearer', 28 | bearerFormat: 'JWT', 29 | }, 30 | }, 31 | }, 32 | security: [ 33 | { 34 | bearerAuth: [], 35 | }, 36 | ], 37 | } 38 | 39 | const cssOptions = { 40 | customCss: ` 41 | .topbar-wrapper img {content:url(/assets/SaTT.png); width:50px; height:auto;}`, 42 | customSiteTitle: 'SaTT', 43 | customfavIcon: '/assets/SaTT-noire.png', 44 | } 45 | 46 | const options = { 47 | swaggerDefinition, 48 | apis: ['./routes/*.js'], 49 | } 50 | const swaggerSpec = swaggerJSDoc(options) 51 | 52 | 53 | 54 | module.exports = {swaggerUi, swaggerSpec, cssOptions}; -------------------------------------------------------------------------------- /libs/transfer/transfer-TRON.js: -------------------------------------------------------------------------------- 1 | const Big = require('big.js') 2 | const { webTronInstance } = require('../../blockchainConnexion') 3 | 4 | module.exports.transferTronTokens = async function ({ 5 | tronAddress, 6 | toAddress, 7 | amount, 8 | privateKey, 9 | max = false, 10 | }) { 11 | let tronWeb = await webTronInstance() 12 | tronWeb.setPrivateKey(privateKey) 13 | let walletAddr = tronWeb.address.fromPrivateKey(privateKey) 14 | tronWeb.setAddress(walletAddr) 15 | if (!tronAddress) throw Error("The account doesn't have a tron address !") 16 | if (!tronWeb.isAddress(tronAddress)) 17 | throw Error('The sender address is not a valid tron address !!') 18 | if (!tronWeb.isAddress(toAddress)) 19 | throw Error('The recipient address is not a valid tron address !!') 20 | if (tronAddress === toAddress) 21 | throw Error('you cant send to your own wallet address !!') 22 | let balance = await tronWeb.trx.getBalance(tronAddress) 23 | JSON.parse(max) && (amount = balance) 24 | if (balance === 0) throw Error('No enough balance to perform withdraw !!') 25 | if (new Big(amount).gt(new Big(balance))) 26 | throw Error('No enough balance to perform withdraw !!') 27 | try { 28 | let result = await tronWeb.trx.sendTransaction(toAddress, amount) 29 | return { 30 | blockHash: result.transaction?.raw_data?.ref_block_hash, 31 | blockNumber: result.transaction?.raw_data?.ref_block_bytes, 32 | transactionHash: result.transaction?.txID, 33 | from: tronAddress, 34 | to: toAddress, 35 | amount: amount, 36 | } 37 | } catch (error) { 38 | return { error: error.message } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /conf/privkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDddRovkVrrL0BX 3 | pGEi3LbN/CKBNmyWn5/PF4SNER4FAH/n+HKO6FfHuB+Y0smOmNlDhYhBku2xOYwn 4 | mEYlDh7H/DPkWdJ3GNil5n5mHloLfXSzkanRxlYFRA8dLSJM1fqVbotQEfuP21u5 5 | 6OxDbYICU7SCFgPl41f7etXP5MxXFtgPTgjVJTaRbhAPWuwTC0dH0EzpY0HfdB6f 6 | 8wWwbkvQP6HjMjaH8BWwYAL1jZ1Y6cm9r49qEynIcr/gnFfkgcgJiaj5uPpZr2sq 7 | Wm0Teex1aTrzF/aci+Dkdz/d41hnC34jlUB4y4aspbz4aikfP5jj8sQeVJHjgZwR 8 | 5Sf7dUfBAgMBAAECggEBAJq+UtfeN6uSzuDuybk0hMAWaH3la6csTtzEUCjKRzGz 9 | kayj3FijXYL+04VT9OchQt99lSJM6q4lyht4ubr2zOdtAU2Uvg3eXLRABR6SItVY 10 | io1XQVSFxGHVlsIKYadS9dAo+Euw5Rk2bDfR3BWZlXjOyJkFjR+75iShRnoIJAjN 11 | brincMh6S/fVptssdel9eZRXCciSAHLzRjsZ4qWSbFAZmpUYu79qlOz3RXzT2A/I 12 | 3vGnt+NVK+elOsDPA8v0k6VtcriLFEf+/mc3VgOmHJjs3sClp+VtubHGypzLmdnx 13 | x03RcUkRpSaKukEZMmTRcT9YknT1UyUdP1lJadNclgECgYEA9Iao5pcaM3/6CXqn 14 | DilVibHCkDD++KFnAI+ag9wRB/gcoHHoL1rKEPXLwQndE4gKUuxy+Sp6f7ZEy5T8 15 | acIhGrPsshSzRDqzNE+64aRJTbtK9fxRWiYKcmn5R1nG59nGSox29IULfi+zGvKc 16 | bvNArzRucNFYud5h2b80l6q6dzECgYEA59lVdvJBafBzVCKqUAhZEhErf752xeCY 17 | TuA2h+/oN4r1S8Fj32UxzQH6CtKU+TK7C49QDgITRiVyx3vWG4hrhj9TBAghVXWm 18 | O+Ut1960HNCgqIG2ssMPhK+NUcW3k6OIY64OezWTY1+TyMObX4JSQ1wq0LzHYmMx 19 | 0v16k/ps1ZECgYEAkq9dDsbCDvbMdXdAU3x0NZ+PCZR6v4eDFJEQrd0L0m4CLjVm 20 | hVG/OaFZUzmphxfqqYfyCIp05bvfVQjQyliMJ0qbyNAmId3ctprFjqpQ1vJtq1Zr 21 | Ltr3FV+BDE5MxbScAQh2K4TMOiw/EwFK2jvOJ8waHE9ZHFbM+CR9ViYyqWECgYEA 22 | ww6dEap1EE0EqldT1GuBjGq3nwy93nK7kTifiDR1uS0GfIqinNMFWAX+uNY8EX/1 23 | z57t6isizhQ5gc0U8CsQ02w5Sp4QdVa62Y9Rx1kNTWTUlZA0BieHycjsa0ydyu99 24 | kudgNZZ4ftVtfy3abTs2PIexWdZJJORxiaJKW28H25ECgYAz0RE57a2CiTFqjrya 25 | CTCHybHVqqJ+syys/XT8B7kdtlAtDNr74lp3I7q6yHCjBxUOrpPRoT8CiQosr1tI 26 | DREUNEc4YbagzjXA5NoggSO/Yw8Ya2yU77bgcErFCcDzbi5oExYzENOR+CIJamj/ 27 | JXv6NCqbFT/8fJsHLBjC4hQyIw== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /conf/ssl/privkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXgv2R+AH5qYJd 3 | N7zJbAfAvI9WwSKPdt119b+XWnGYAi0fxL/MwGCfGkgkfm7nrIOq2k0Z464Vq3pd 4 | cwb6N4t1NnIl49eUxygeGR3HhWBinczHIBvadtx6ZpV8CHj8XZ+ouHEBdWa+Gl4M 5 | jZnW4B+g/RLrVqrBLUWKhyTETDNZPTNoGPvwrZoIBvS7oKLjO0XVtFhE3NQSiJgl 6 | /PfgbjmyMJkBJOP5LAP/CdjT1stTHOS9D6z3ulj6x9YXeFAsNyIic4E3Cg2bBwkb 7 | n5upoxFdpVHZGAg64UXxE1xNvXfY7EB23fgNoamcTffUBVHnMPgswwLzkdGSt2z6 8 | rNyaglTTAgMBAAECggEAUF8oo9xjGDHQTWVxAYlJZuarakZC1lAVDV3l4tM3E+KT 9 | 44ojoX+JSSyrBPkl8T6UKA6bvHD9xlUaIGm6i2xVlRQGA/1xs6mGW5swUO174atJ 10 | 6GUgHhw/42IIk6YxQKTF201Vz55x/6mjs3jHi6wv/4ECIkRDECILEjuOSarFZ5zN 11 | MCVb9Ebc7N4BxqZKf/S1ZfeM3dGAbe4tKLUt2EnatpLpOVJBvfI8ONnDMs4xpm1w 12 | U4qCb31OlkolR6UXDXZ8eRbgwVr9VwVZEC3MH6IOvOXkZfnJ8tqmTtICPBFzU6T9 13 | gVWo80CttDSBw+tWtswdLRu2UM1uORUKHAORhoSHiQKBgQDs/Jc1M3e1JDy2uDEw 14 | Z+MNN5SDhT7IVV8ubWnKURjohw8ZAON6mPYj4K+HjGzKRv/CqiKc384IbiZodUYH 15 | n0qKaiPPqSIT+xOle6nPTRlJvih/v0y008sGPgcJnKjcQ/E5BsodmB69vgXRzauV 16 | 7K9ac4cq9CBGfXl3z1AXK+76/QKBgQDozVSMM909Axkd4dVZYg7FuBR34V8yssvj 17 | S9lhecJyoQr7irLQrkZhjCISDPwf+0qSoUL+VEc1f6qTpYtWlzGY7c9SyAJc4NTL 18 | CqbfO0J/uoEiCpAS8ruymLPDV0nYDxtBsSGPpIi0HYXaNUNtlpLgvDWo1msyFroD 19 | HCg/d0ogDwKBgHZYzcoroaQ8LHWzFh1uQ9zd3LSxXeD9gULWMPZv+Vhl2gxKfU9E 20 | A+d21TGD1vBM9HxqKk7dFS7wkw2nQwmbasYkqy2Q8Qu5Xt5NG0gC4JYK+H6TMeM7 21 | wS+k2i7apRkadORdl6GfzfpDYvSbGQ0N3aP1/ZJdx6BsGLTUOtLXhcihAoGBAL/V 22 | kzoE8uX3y5aoJZqGBw4+Zf9zI3Mvins+YV7Fasnyko48+KSlNzHiu6CMOqZP+F9j 23 | q0TQRe17yh/oZi1wYVpXfGQGlIvcaPz3RhLlTiLamNZoRdiXVLwSwO7S2vLDX/59 24 | 693mAxAI0+e/xFRlo5q0/LKoHaUkvRsa9L93mQlZAoGAZ0c4TrSuTsW/Q5vNhpQP 25 | Ao0pC2AWZotfpavFbGkEtSdI1xzppd9xdpazPFRoT/yxvzb0WVplmggxX2Pzsicf 26 | /0QBHGNrzXp6VCNeCKgomttrW6R2dD9hKZYuXNJLQnsLO4iPYZ5fp8JlvYSvSow5 27 | 1ftYyYeFWmDNkWssHhFFen0= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /web3/web3-connection.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3') 2 | 3 | const { 4 | Erc20NetworkConstant, 5 | Bep20NetworkConstant, 6 | PolygonNetworkConstant, 7 | BttNetworkConstant, 8 | ArtheraNetworkConstant, 9 | } = require('../conf/const') 10 | 11 | const options = { 12 | timeout: 30000, 13 | 14 | clientConfig: { 15 | // Useful if requests are largeS 16 | maxReceivedFrameSize: 100000000, // bytes - default: 1MiB 17 | maxReceivedMessageSize: 100000000, // bytes - default: 8MiB 18 | 19 | // Useful to keep a connection alive 20 | keepalive: true, 21 | keepaliveInterval: 60000, // ms 22 | }, 23 | 24 | // Enable auto reconnection 25 | reconnect: { 26 | auto: true, 27 | delay: 5000, // ms 28 | maxAttempts: 5, 29 | onTimeout: false, 30 | }, 31 | } 32 | 33 | const networkProviders = {} 34 | 35 | networkProviders[Erc20NetworkConstant] = process.env.WEB3_URL 36 | networkProviders[Bep20NetworkConstant] = process.env.WEB3_URL_BEP20 37 | networkProviders[PolygonNetworkConstant] = process.env.WEB3_URL_POLYGON 38 | networkProviders[BttNetworkConstant] = process.env.WEB3_URL_BTT 39 | networkProviders[ArtheraNetworkConstant] = process.env.WEB3_URL_ARTHERA 40 | 41 | const networkProvidersOptions = {} 42 | 43 | networkProvidersOptions[Erc20NetworkConstant] = options 44 | networkProvidersOptions[Bep20NetworkConstant] = options 45 | networkProvidersOptions[PolygonNetworkConstant] = options 46 | networkProvidersOptions[BttNetworkConstant] = options 47 | networkProvidersOptions[ArtheraNetworkConstant] = options 48 | 49 | const getWeb3Connection = function (providerUrl, providerOptions) { 50 | return new Web3(getHttpProvider(providerUrl, providerOptions)) 51 | } 52 | 53 | const getHttpProvider = function (providerUrl, providerOptions) { 54 | return new Web3.providers.HttpProvider(providerUrl, providerOptions) 55 | } 56 | 57 | module.exports = { 58 | getWeb3Connection, 59 | getHttpProvider, 60 | networkProviders, 61 | networkProvidersOptions, 62 | } 63 | -------------------------------------------------------------------------------- /middleware/verifySignature.middleware.js: -------------------------------------------------------------------------------- 1 | const verifySignature = require('./../web3/verifySignature'); 2 | const Joi = require('joi'); 3 | 4 | const verifySignatureMiddleware = (req, res, next) => { 5 | const signature = req.header('X-Signature'); 6 | const address = req.header('X-Address'); 7 | const message = req.header('X-Message'); 8 | 9 | if (verifySignature(message, signature, address)) { 10 | req.address = address; 11 | return next(); 12 | } else { 13 | return res.status(401).json({ message: 'Invalid signature' }); 14 | } 15 | }; 16 | 17 | const validationMiddleware = (schema, property) => (req, res, next) => { 18 | const { error } = schema.validate(req[property]); 19 | if (error) { 20 | return res.status(400).json({ message: 'Validation error', error: error.details }); 21 | } else { 22 | next(); 23 | } 24 | }; 25 | 26 | const schemas = { 27 | userIdCheckSchema: Joi.object({ 28 | idUser: Joi.number().required(), 29 | }), 30 | idCheckSchema: Joi.object({ 31 | id: Joi.string().required(), 32 | }), 33 | checkFileSchema: Joi.object({ 34 | file: Joi.custom((value) => { 35 | if (value && value.mimetype && value.mimetype.startsWith('image/')) { 36 | return value; 37 | } else throw Error('File is required'); 38 | }), 39 | }), 40 | addKitsSchema: Joi.object({ 41 | link: Joi.string(), 42 | campaign: Joi.string().required() 43 | }), 44 | gainsSchema: Joi.object({ 45 | idProm: Joi.string().required(), 46 | pass: Joi.string().required(), 47 | hash: Joi.string().required() 48 | }), 49 | }; 50 | 51 | module.exports = { 52 | verifySignatureMiddleware, 53 | validationMiddleware, 54 | idCheckValidation: validationMiddleware(schemas.idCheckSchema, 'params'), 55 | addKitsValidation: validationMiddleware(schemas.checkFileSchema, 'file', schemas.addKitsSchema, 'body'), 56 | externalGainsValidation: validationMiddleware(schemas.gainsSchema, 'body'), 57 | 58 | }; 59 | -------------------------------------------------------------------------------- /model/campaignLink.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const campaignLinkSchema = mongoose.Schema( 4 | { 5 | id_prom: { type: String }, 6 | typeSN: { type: Number }, 7 | idUser: { type: String }, 8 | status: { type: mongoose.Schema.Types.Mixed, default: false }, 9 | type: { type: String, default: 'waiting_for_validation' }, 10 | id_wallet: { type: String }, 11 | idPost: { type: String }, 12 | id_campaign: { type: String }, 13 | isPayed: { type: Boolean, default: false }, 14 | typeURL: { type: String }, 15 | appliedDate: { type: Number }, 16 | acceptedDate: { type: Number }, 17 | lastHarvestDate: { type: Number }, 18 | oracle: { type: String }, 19 | abosNumber: { type: Number, default: 0 }, 20 | instagramUserName: { type: String }, 21 | likes: { type: Number, default: 0 }, 22 | shares: { type: Number, default: 0 }, 23 | views: { type: Number, default: 0 }, 24 | totalToEarn: { type: String }, 25 | payedAmount: { type: String }, 26 | media_url: { type: String }, 27 | reason: { type: [] }, 28 | deleted: { type: Boolean }, 29 | linkedinId: { type: String }, 30 | userExternal: {type: Boolean , default: false}, 31 | applyerSignature: { 32 | messageHash: { type: String }, 33 | v: { type: String }, 34 | r: { type: String }, 35 | s: { type: String }, 36 | signature: { type: String }, 37 | }, 38 | approvalSignature: { 39 | messageHash: { type: String }, 40 | v: { type: String }, 41 | r: { type: String }, 42 | s: { type: String }, 43 | signature: { type: String }, 44 | }, 45 | }, 46 | {timestamps: true, 47 | collection: 'campaign_link', 48 | } 49 | ) 50 | campaignLinkSchema.index({ 'applyerSignature.signature': 1 }); 51 | const CampaignLink = mongoose.model('campaign_link', campaignLinkSchema) 52 | module.exports = CampaignLink 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yaml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: File a bug/issue 3 | title: '[BUG] <title>' 4 | labels: [Bug, Triage] 5 | assignees: 6 | - Chef-Cheems 7 | - chef-jojo 8 | body: 9 | - type: checkboxes 10 | attributes: 11 | label: Is there an existing issue for this? 12 | description: Please search to see if an issue already exists for the bug you encountered. 13 | options: 14 | - label: I have searched the existing issues 15 | required: true 16 | - type: dropdown 17 | attributes: 18 | label: Product 19 | description: Which page or product does this relate to? 20 | multiple: false 21 | options: 22 | - Trade 23 | - Farms 24 | - Syrup Pools 25 | - Lottery 26 | - Prediction 27 | - IFO 28 | - Info 29 | - NFT 30 | - Other 31 | validations: 32 | required: true 33 | - type: textarea 34 | attributes: 35 | label: Current Behavior 36 | description: A concise description of what you're experiencing. 37 | validations: 38 | required: true 39 | - type: textarea 40 | attributes: 41 | label: Expected Behavior 42 | description: A concise description of what you expected to happen. 43 | validations: 44 | required: true 45 | - type: textarea 46 | attributes: 47 | label: Steps To Reproduce 48 | description: Steps to reproduce the behavior. 49 | placeholder: | 50 | 1. In this environment... 51 | 2. With this config... 52 | 3. Run '...' 53 | 4. See error... 54 | validations: 55 | required: true 56 | - type: textarea 57 | attributes: 58 | label: Environment 59 | description: | 60 | example 1: 61 | - **Device**: MacBook Pro 62 | - **OS**: Big Sur 11.3.1 63 | - **Brower**: Chome 64 | - **Wallet**: Metamask 65 | 66 | example 2: 67 | - **Device**: IPhone XR 68 | - **OS**: IOS 13 69 | - **Brower**: N/A 70 | - **Wallet**: Metamask app 71 | value: | 72 | - Device: 73 | - OS: 74 | - Browser: 75 | - Wallet: 76 | render: markdown 77 | validations: 78 | required: true 79 | - type: textarea 80 | attributes: 81 | label: Anything else? 82 | description: | 83 | Links? References? Anything that will give us more context about the issue you are encountering! 84 | 85 | Tip: You can attach images by clicking this area to highlight it and then dragging files in. 86 | validations: 87 | required: false 88 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | 3 | .env.local 4 | 5 | .env.testnet 6 | 7 | .env. 8 | 9 | uploads 10 | # Logs 11 | logs 12 | *.log 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | .idea 18 | 19 | # Diagnostic reports (https://nodejs.org/api/report.html) 20 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 21 | 22 | # Runtime data 23 | pids 24 | *.pid 25 | *.seed 26 | *.pid.lock 27 | .idea 28 | 29 | 30 | # Directory for instrumented libs generated by jscoverage/JSCover 31 | lib-cov 32 | 33 | # Coverage directory used by tools like istanbul 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | .nyc_output 39 | 40 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 41 | .grunt 42 | 43 | # Bower dependency directory (https://bower.io/) 44 | bower_components 45 | 46 | # node-waf configuration 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | build/Release 51 | 52 | # Dependency directories 53 | node_modules/ 54 | jspm_packages/ 55 | 56 | #config files 57 | conf/wallets/bep20.json 58 | conf/wallets/campaign.json 59 | conf/wallets/campaign.polygon.json 60 | conf/wallets/campaign.arthera.json 61 | conf/ssl/fullchain.pem 62 | conf/ssl/privkey.pem 63 | conf/satt-token-firebase-adminsdk-fwxcj-2215bda3fa.json 64 | # TypeScript v1 declaration files 65 | typings/ 66 | 67 | # TypeScript cache 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | .npm 72 | 73 | # Optional eslint cache 74 | .eslintcache 75 | 76 | # Microbundle cache 77 | .rpt2_cache/ 78 | .rts2_cache_cjs/ 79 | .rts2_cache_es/ 80 | .rts2_cache_umd/ 81 | 82 | # Optional REPL history 83 | .node_repl_history 84 | 85 | # Output of 'npm pack' 86 | *.tgz 87 | 88 | # Yarn Integrity file 89 | .yarn-integrity 90 | 91 | # dotenv environment variables file 92 | 93 | .env.test 94 | .env 95 | 96 | # parcel-bundler cache (https://parceljs.org/) 97 | .cache 98 | 99 | # Next.js build output 100 | .next 101 | 102 | # Nuxt.js build / generate output 103 | .nuxt 104 | dist 105 | 106 | # Gatsby files 107 | .cache/ 108 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 109 | # https://nextjs.org/blog/next-9-1#public-directory-support 110 | # public 111 | 112 | # vuepress build output 113 | .vuepress/dist 114 | 115 | # Serverless directories 116 | .serverless/ 117 | 118 | # FuseBox cache 119 | .fusebox/ 120 | 121 | # DynamoDB Local files 122 | .dynamodb/ 123 | 124 | # TernJS port file 125 | .tern-port 126 | 127 | # Vscode extentions related files 128 | .history 129 | .vscode 130 | -------------------------------------------------------------------------------- /libs/transfer/transfer-btc.js: -------------------------------------------------------------------------------- 1 | const bip38 = require('bip38') 2 | const wif = require('wif') 3 | const child = require('child_process') 4 | const rp = require('axios'); 5 | const bitcoinjs = require('bitcoinjs-lib') 6 | const config = require('./config') 7 | 8 | module.exports.transferBTC = async function ({ 9 | to, 10 | amount, 11 | walletPassword, 12 | account, 13 | }) { 14 | var escpass = walletPassword.replace(/'/g, "\\'") 15 | 16 | var priv = bip38.decrypt(account.btc.ek, escpass) 17 | 18 | var encode = wif.encode(0x80, priv.privateKey, priv.compressed) 19 | 20 | var addr = account.btc.addressSegWitCompat 21 | 22 | var utxo = JSON.parse( 23 | child.execSync( 24 | config.BTC_CMD + ' listunspent 1 1000000 \'["' + addr + '"]\'' 25 | ) 26 | ) 27 | 28 | if (!utxo.length) { 29 | return { error: 'insufficient funds ' } 30 | } 31 | 32 | var max = 0.0 33 | for (var i = 0; i < utxo.length; i++) { 34 | max += parseFloat(utxo[i].amount) 35 | } 36 | max = Math.floor(parseFloat(max) * 100000000) 37 | 38 | var body = await rp({ uri: config.BTS_FEES, json: true }) 39 | var feeRate = 15 // parseInt(body.fastestFee); 40 | 41 | var maxFee = 20000 42 | 43 | const keyPair = bitcoinjs.ECPair.fromWIF(encode) 44 | const txb = new bitcoinjs.TransactionBuilder() 45 | 46 | var input_sum = 0 47 | var fee = (45 + utxo.length * 93) * feeRate 48 | for (var i = 0; i < utxo.length; i++) { 49 | txb.addInput(utxo[i].txid, parseInt(utxo[i].vout)) 50 | input_sum += Math.round(parseFloat(utxo[i].amount) * 100000000) 51 | } 52 | var change = input_sum - parseInt(amount) - (fee + 34 * feeRate) 53 | txb.addOutput(to, parseInt(amount)) 54 | 55 | if (change > fee) { 56 | txb.addOutput(addr, parseInt(change)) 57 | fee += 34 * feeRate 58 | } 59 | 60 | if (parseInt(amount) + parseInt(fee) > max) { 61 | return { 62 | error: 'insufficient funds for gas', 63 | } 64 | } 65 | 66 | const p2wpkh = bitcoinjs.payments.p2wpkh({ pubkey: keyPair.publicKey }) 67 | const p2sh = bitcoinjs.payments.p2sh({ redeem: p2wpkh }) 68 | 69 | for (var i = 0; i < utxo.length; i++) { 70 | txb.sign( 71 | i, 72 | keyPair, 73 | p2sh.redeem.output, 74 | null, 75 | Math.round(parseFloat(utxo[i].amount) * 100000000) 76 | ) 77 | } 78 | var tx = txb.build() 79 | 80 | var signed = tx.toHex() 81 | var transactionHash = tx.getId() 82 | 83 | var rec = child.execSync( 84 | config.BTC_CMD + ' sendrawtransaction "' + signed + '"' 85 | ) 86 | return { transactionHash } 87 | } 88 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | const ip = require("ip"); 7 | exports.ip = ip.address() 8 | 9 | var app = require('../app'); 10 | var fs = require('fs') 11 | 12 | var debug = require('debug')('myapp:server') 13 | var https = require('https'); 14 | var cluster = require('cluster'); 15 | 16 | //Returns an array of objects containing information about each logical CPU core. 17 | var numCPUs = require('os').cpus().length; 18 | /** 19 | * Get port from environment and store in Express. 20 | */ 21 | 22 | 23 | var port = normalizePort(process.env.LISTEN_PORT || '3015'); 24 | app.set('port', port); 25 | 26 | /** 27 | * Create HTTP server. 28 | */ 29 | 30 | var server = https.createServer( { 31 | key: fs.readFileSync(process.env.SSL_KEY, 'utf8'), 32 | cert: fs.readFileSync(process.env.SSL_CER, 'utf8'), 33 | },app); 34 | 35 | if (cluster.isMaster) { 36 | // Fork workers. 37 | for (var i = 0; i < numCPUs; i++) { 38 | cluster.fork(); 39 | } 40 | 41 | cluster.on('death', function(worker) { 42 | }); 43 | } else { 44 | server.listen(port); 45 | } 46 | 47 | server.on('error', onError); 48 | server.on('listening', onListening); 49 | 50 | /** 51 | * Normalize a port into a number, string, or false. 52 | */ 53 | 54 | function normalizePort(val) { 55 | var port = parseInt(val, 10); 56 | 57 | if (isNaN(port)) { 58 | // named pipe 59 | return val; 60 | } 61 | 62 | if (port >= 0) { 63 | // port number 64 | return port; 65 | } 66 | 67 | return false; 68 | } 69 | 70 | /** 71 | * Event listener for HTTP server "error" event. 72 | */ 73 | 74 | function onError(error) { 75 | if (error.syscall !== 'listen') { 76 | throw error; 77 | } 78 | 79 | var bind = typeof port === 'string' ? 80 | 'Pipe ' + port : 81 | 'Port ' + port; 82 | 83 | // handle specific listen errors with friendly messages 84 | switch (error.code) { 85 | case 'EACCES': 86 | console.error(bind + ' requires elevated privileges'); 87 | process.exit(1); 88 | break; 89 | case 'EADDRINUSE': 90 | console.error(bind + ' is already in use'); 91 | process.exit(1); 92 | break; 93 | default: 94 | throw error; 95 | } 96 | } 97 | 98 | /** 99 | * Event listener for HTTP server "listening" event. 100 | */ 101 | 102 | function onListening() { 103 | var addr = server.address(); 104 | var bind = typeof addr === 'string' ? 105 | 'pipe ' + addr : 106 | 'port ' + addr.port; 107 | debug('Listening on ' + bind); 108 | } -------------------------------------------------------------------------------- /model/campaigns.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const campaignsSchema = mongoose.Schema( 4 | { 5 | title: { type: String }, 6 | description: { type: String }, 7 | resume: { type: String }, 8 | brand: { type: String }, 9 | reference: { type: String }, 10 | countries: [ 11 | { 12 | item_id: { type: Number }, 13 | item_text: { type: String }, 14 | }, 15 | ], 16 | token: { 17 | name: { type: String }, 18 | type: { type: String }, 19 | addr: { type: String }, 20 | }, 21 | tags: [{ type: String }], 22 | endDate: { type: mongoose.Schema.Types.Mixed }, 23 | startDate: { type: mongoose.Schema.Types.Mixed }, 24 | remuneration: { type: String }, 25 | ratios: [ 26 | { 27 | like: { type: String }, 28 | view: { type: String }, 29 | share: { type: String }, 30 | reachLimit: { type: String }, 31 | oracle: { type: String }, 32 | }, 33 | ], 34 | bounties: [ 35 | { 36 | oracle: { type: String }, 37 | categories: [ 38 | { 39 | minFollowers: { type: Number }, 40 | maxFollowers: { type: Number }, 41 | reward: { type: String }, 42 | }, 43 | ], 44 | }, 45 | ], 46 | missions: [ 47 | { 48 | oracle: { type: String }, 49 | sub_missions: [ 50 | { 51 | mission: { type: String }, 52 | }, 53 | ], 54 | }, 55 | ], 56 | cost: { type: String }, 57 | cost_usd: { type: String }, 58 | idNode: { type: String }, 59 | type: { type: String }, 60 | cover: { type: String }, 61 | logo: { type: String }, 62 | coverSrc: { type: String }, 63 | coverMobile: { type: String }, 64 | coverSrcMobile: { type: String }, 65 | contract: { type: String }, 66 | limit : {type : Number, default : 0}, 67 | dataUrl: { type: String }, 68 | funds: [{ type: String }, { type: String }], 69 | hash: { type: String }, 70 | transactionHash: { type: String }, 71 | walletId: { type: String }, 72 | launchDate : { type: Date }, 73 | retrieved: {type : Boolean} 74 | 75 | }, 76 | { timestamps: true, collection: 'campaigns' } 77 | ) 78 | 79 | const Campaigns = mongoose.model('campaigns', campaignsSchema) 80 | 81 | module.exports = Campaigns 82 | -------------------------------------------------------------------------------- /model/wallet.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const walletSchema = mongoose.Schema( 4 | { 5 | UserId: { type: Number }, 6 | keystore: { 7 | version: { type: Number }, 8 | id: { type: String }, 9 | address: { type: String }, 10 | crypto: { 11 | ciphertext: { type: String }, 12 | cipherparams: { 13 | iv: { type: String }, 14 | }, 15 | cipher: { type: String }, 16 | kdf: { type: String }, 17 | kdfparams: { 18 | dklen: { type: Number }, 19 | salt: { type: String }, 20 | n: { type: Number }, 21 | r: { type: Number }, 22 | p: { type: Number }, 23 | }, 24 | mac: { type: String }, 25 | }, 26 | }, 27 | num: { type: Number }, 28 | btc: { 29 | publicKey: { type: String }, 30 | addressSegWitCompat: { type: String }, 31 | addressSegWit: { type: String }, 32 | publicKeySegWit: { type: String }, 33 | ek: { type: String }, 34 | }, 35 | mnemo: { type: String }, 36 | tronAddress: { type: String }, 37 | tronValue: { type: String }, 38 | walletV2: { 39 | keystore: { 40 | version: { type: Number }, 41 | id: { type: String }, 42 | address: { type: String }, 43 | crypto: { 44 | ciphertext: { type: String }, 45 | cipherparams: { 46 | iv: { type: String }, 47 | }, 48 | cipher: { type: String }, 49 | kdf: { type: String }, 50 | kdfparams: { 51 | dklen: { type: Number }, 52 | salt: { type: String }, 53 | n: { type: Number }, 54 | r: { type: Number }, 55 | p: { type: Number }, 56 | }, 57 | mac: { type: String }, 58 | }, 59 | }, 60 | btc: { 61 | publicKey: { type: String }, 62 | addressSegWitCompat: { type: String }, 63 | addressSegWit: { type: String }, 64 | publicKeySegWit: { type: String }, 65 | ek: { type: String }, 66 | }, 67 | mnemo: { type: String }, 68 | tronAddress: { type: String }, 69 | tronValue: { type: String }, 70 | }, 71 | }, 72 | { 73 | collection: 'wallet', 74 | } 75 | ) 76 | 77 | const Wallet = mongoose.model('wallet', walletSchema) 78 | 79 | module.exports = Wallet 80 | -------------------------------------------------------------------------------- /manager/notification.js: -------------------------------------------------------------------------------- 1 | const { JWT } = require('google-auth-library') 2 | const serviceAccount = require('../conf/satt-token-firebase-adminsdk-fwxcj-2215bda3fa.json') 3 | const axios = require('axios') 4 | 5 | const getAccessToken = () => { 6 | return new Promise((resolve, reject) => { 7 | let serAccount = serviceAccount 8 | const key = serAccount 9 | const jwtClient = new JWT( 10 | key.client_email, 11 | null, 12 | key.private_key, 13 | ['https://www.googleapis.com/auth/cloud-platform'], 14 | null 15 | ) 16 | jwtClient.authorize((err, tokens) => { 17 | if (err) { 18 | reject(err) 19 | return 20 | } 21 | resolve(tokens.access_token) 22 | }) 23 | }) 24 | } 25 | 26 | exports.sendNotification = async (data) => { 27 | let fireBaseAccessToken = await getAccessToken() 28 | var axiosOptions = { 29 | url: 'https://fcm.googleapis.com/v1/projects/satt-token/messages:send', 30 | method: 'post', 31 | headers: { 32 | 'Content-Type': 'application/json', 33 | Authorization: 'Bearer ' + fireBaseAccessToken, 34 | }, 35 | data: JSON.stringify(data), 36 | } 37 | axios(axiosOptions) 38 | .then((response) => {}) 39 | .catch((error) => {}) 40 | } 41 | 42 | exports.sendNotificationTest = async (req, res) => { 43 | let notification = { 44 | idNode: '0149', 45 | type: 'NotifType', 46 | status: 'done', 47 | label: 'label', 48 | isSeen: false, 49 | isSend: false, 50 | attachedEls: { 51 | id: 149, 52 | }, 53 | created: new Date(), 54 | } 55 | //let token="dMhtAVFNRAqSrlHtePzqk_:APA91bFFr8q8j_XBcZDGSnPvrVgSJvD3dxXP6thieH_LqGRb-joMN17fsLEgTDF6mhoXX_hO11wajyDICdGs203RVARUIxOZ8u84g0KjD9umoEeEh5_hDanflpNub1EmnWhZiw1iXGsV"; 56 | let token = 57 | 'ckGww57_lZ23aTxajLkzyh:APA91bGaqiJ7ny5CE0Jj6TOFOdiDYjW8UFpzSnHLy3NyPB5YHj6Hc232GodJP1o8ZyXK5Z6v11HVgVKmkmU9AfbJgDPx0v9MDckN' 58 | let data = { 59 | message: { 60 | token, 61 | data: { 62 | obj: JSON.stringify(notification), 63 | }, 64 | }, 65 | } 66 | 67 | let fireBaseAccessToken = await getAccessToken() 68 | var clientServerOptions = { 69 | url: 'https://fcm.googleapis.com/v1/projects/satt-token/messages:send', 70 | data: JSON.stringify(data), 71 | method: 'POST', 72 | headers: { 73 | 'Content-Type': 'application/json', 74 | Authorization: 'Bearer ' + fireBaseAccessToken, 75 | }, 76 | } 77 | 78 | axios(clientServerOptions) 79 | .then((response) => { 80 | res.send(response.data) 81 | }) 82 | .catch((error) => { 83 | console.error(error) 84 | }) 85 | } 86 | 87 | // module.exports = { sendNotification } 88 | -------------------------------------------------------------------------------- /contracts/PriceGap.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5; 2 | 3 | contract owned { 4 | address payable public owner; 5 | 6 | constructor () public { 7 | owner = msg.sender; 8 | } 9 | 10 | modifier onlyOwner { 11 | require(msg.sender == owner); 12 | _; 13 | } 14 | 15 | function transferOwnership(address payable newOwner) onlyOwner public { 16 | owner = newOwner; 17 | } 18 | } 19 | 20 | interface IERC20 { 21 | 22 | function transfer(address _to, uint256 _value) external; 23 | function transferFrom(address _from, address _to, uint256 _value) external returns (bool success); 24 | } 25 | 26 | contract ERC20Holder is owned { 27 | 28 | 29 | function tokenFallback(address _from, uint _value, bytes memory _data) pure public returns (bytes32 hash) { 30 | bytes32 tokenHash = keccak256(abi.encodePacked(_from,_value,_data)); 31 | return tokenHash; 32 | } 33 | 34 | function() external payable {} 35 | 36 | function withdraw() onlyOwner public { 37 | owner.transfer(address(this).balance); 38 | } 39 | 40 | function transferToken (address token,address to,uint256 val) public onlyOwner { 41 | IERC20 erc20 = IERC20(token); 42 | erc20.transfer(to,val); 43 | } 44 | 45 | } 46 | 47 | 48 | contract priceGap is ERC20Holder { 49 | 50 | address satt = address(0xDf49C9f599A0A9049D97CFF34D0C30E468987389); 51 | address signer = address(0xb0959d3CAEF1a0526cA6Ca9069994A80B8baffC8); 52 | 53 | mapping (address => bool) paid; 54 | 55 | 56 | constructor () public { 57 | } 58 | 59 | function setSigner (address a) public onlyOwner { 60 | signer = a; 61 | } 62 | 63 | function setSatt (address a) public onlyOwner { 64 | satt = a; 65 | } 66 | 67 | function getGap (address a,uint256 b, uint8 v, bytes32 r, bytes32 s) public { 68 | 69 | require(!paid[a]); 70 | bytes32 h = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encode(a,b)))); 71 | require( ecrecover(h, v, r, s) == signer); 72 | IERC20 erc20 = IERC20(satt); 73 | 74 | paid[a] = true; 75 | 76 | uint256 amt = b*1000000000000000000; 77 | 78 | erc20.transfer(a,amt); 79 | 80 | } 81 | 82 | function testhash (address a,uint256 b, uint8 v, bytes32 r, bytes32 s) public view returns (bytes32) { 83 | bytes32 i = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encode(a,b)))); 84 | 85 | return i; 86 | } 87 | 88 | function test (address a,uint256 b, uint8 v, bytes32 r, bytes32 s) public view returns (address) { 89 | bytes32 k = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encode(a,b)))); 90 | address j = ecrecover(k, v, r, s); 91 | 92 | return j; 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /model/UserArchive.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const userArchivedSchema = mongoose.Schema( 4 | { 5 | _id: { type: Number }, 6 | first_name: { type: String }, 7 | name: { type: String }, 8 | idSn: { type: Number }, 9 | idOnSn: { type: String }, 10 | idOnSn2: { type: String }, 11 | idOnSn3: { type: String }, 12 | email: { type: String }, 13 | username: { type: String }, 14 | firstName: { type: String }, 15 | lastName: { type: String }, 16 | lastLogin: { type: Date }, 17 | newsLetter: { type: Boolean }, 18 | onBoarding: { type: Boolean }, 19 | account_locked: { type: Boolean }, 20 | failed_count: { type: Number }, 21 | date_locked: { type: Number }, 22 | enabled: { type: Number }, 23 | locale: { type: String }, 24 | userSatt: { type: Boolean }, 25 | picLink: { type: String }, 26 | dateFirstAttempt: { type: Number }, 27 | completed: { type: Boolean }, 28 | password: { type: String }, 29 | secureCode: { 30 | code: { type: Number }, 31 | expiring: { type: Number }, 32 | type: { type: String }, 33 | }, 34 | hasWallet: { type: Boolean }, 35 | hasWalletV2: { type: Boolean, default: false }, 36 | passphrase: { type: Boolean }, 37 | is2FA: { type: Boolean }, 38 | secret: { type: String }, 39 | photoUpdated: { type: Boolean }, 40 | isChanged: { type: Boolean }, 41 | birthday: { type: String }, 42 | gender: { type: String }, 43 | daily: [ 44 | { 45 | Date: { type: Number }, 46 | Balance: { type: String }, 47 | convertDate: { type: String }, 48 | }, 49 | ], 50 | weekly: [ 51 | { 52 | Date: { type: Number }, 53 | Balance: { type: String }, 54 | convertDate: { type: String }, 55 | }, 56 | ], 57 | monthly: [ 58 | { 59 | Date: { type: Number }, 60 | Balance: { type: String }, 61 | convertDate: { type: String }, 62 | }, 63 | ], 64 | address: { type: String }, 65 | city: { type: String }, 66 | country: { type: String }, 67 | zipCode: { type: String }, 68 | visitPassphrase: { type: Boolean }, 69 | fireBaseAccessToken: { type: String }, 70 | phone: { 71 | number: { type: String }, 72 | internationalNumber: { type: String }, 73 | nationalNumber: { type: String }, 74 | e164Number: { type: String }, 75 | countryCode: { type: String }, 76 | dialCode: { type: String }, 77 | }, 78 | }, 79 | { timestamps: true, strict: false, collection: 'sn_user_archived' } 80 | ) 81 | const UserArchived = mongoose.model('sn_user_archived', userArchivedSchema) 82 | module.exports = UserArchived 83 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "develop", mainnet ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "develop" ] 20 | schedule: 21 | - cron: '33 12 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Use only 'java' to analyze code written in Java, Kotlin or both 38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 40 | 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v3 44 | 45 | # Initializes the CodeQL tools for scanning. 46 | - name: Initialize CodeQL 47 | uses: github/codeql-action/init@v2 48 | with: 49 | languages: ${{ matrix.language }} 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | 54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 55 | # queries: security-extended,security-and-quality 56 | 57 | 58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 59 | # If this step fails, then you should remove it and run the build manually (see below) 60 | - name: Autobuild 61 | uses: github/codeql-action/autobuild@v2 62 | 63 | # ℹ️ Command-line programs to run using the OS shell. 64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 65 | 66 | # If the Autobuild fails above, remove it and uncomment the following three lines. 67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 68 | 69 | # - run: | 70 | # echo "Run, Build Application using script" 71 | # ./location_of_script_within_repo/buildscript.sh 72 | 73 | - name: Perform CodeQL Analysis 74 | uses: github/codeql-action/analyze@v2 75 | with: 76 | category: "/language:${{matrix.language}}" 77 | -------------------------------------------------------------------------------- /libs/transfer/readme.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This package act as a transaction signer to sign and send token funds from one account address to another. 4 | 5 | # Installation 6 | 7 | ``` 8 | npm i @atayen-org/transfer 9 | ``` 10 | 11 | # Methods 12 | 13 | ## transferTokens 14 | 15 | Use this function to transfer native or custom EVM tokens. However you need to provide token's SmartContract address and ABI if you want to transfer custom tokens. 16 | 17 | | Properties | Description | 18 | | ------------------------- | ------------------------------------------------------------------------------------------- | 19 | | fromAddress | Sender address | 20 | | toAddress | Receiver address | 21 | | amount | Amount in wei (make sure it's in wei very important !!) | 22 | | tokenSmartContractAddress | Set to null by default so it will send native tokens | 23 | | tokenSmartContractAbi | Set to null by default | 24 | | provider | You network provider object | 25 | | walletPassword | Your secret encryption account password | 26 | | encryptedPrivateKey | Will be used to decrypt your account along with your encryption password ( walletPasswrod ) | 27 | 28 | ## transferBTC 29 | 30 | For the bitcoin protocol 31 | 32 | | Properties | Description | 33 | | -------------- | ----------------------------------------------- | 34 | | to | the receiver address | 35 | | amount | amount in satochi unit | 36 | | walletPassword | Your secret account password | 37 | | account | account that contain your encrypted btc account | 38 | 39 | # Usage 40 | 41 | ```js 42 | const { transferTokens } = require('@atayen-org/transfer'); 43 | const Web3 = require('web3') 44 | 45 | const provider = new Web3.providers.HttpProvider("http_provider_url") 46 | const tokenSmartContractAbi = // you need to provider smart contract abi 47 | const encryptedPrivateKey = // An encrypted version of your private key 48 | 49 | transferTokens({ 50 | fromAddress: "0x7ccf8e6b1ea2c018ec133299b4d41de4e5b28304", 51 | toAddress: "0xc8640bc88b5751674e3535ecd398962b69ba9845", 52 | amount: "10000000000000000000", 53 | tokenSmartContractAddress: "0x4CB4473Af06B844d06b5eDeF08983B2C5C61e5af", 54 | tokenSmartContractAbi 55 | provider, 56 | walletPassword: "yourSecretWalletPassword", 57 | encryptedPrivateKey, 58 | }).then((result) => ) 59 | 60 | // it will return a promise with the below value 61 | /* 62 | 63 | xX Example values on testnet here Xx 64 | { 65 | blockHash: '0x3e1962d40d9e4d0d44646cf96d4c17159dda6d47eabc6fe24b7ce3c99889c6a4', 66 | blockNumber: 20990200, 67 | transactionHash: '0xe48b9d35688fb83065791a93f05249e31256e04309d884b665bbada537d03c46', 68 | from: '0x7ccf8e6b1ea2c018ec133299b4d41de4e5b28304', 69 | to: '0xc8640bc88b5751674e3535ecd398962b69ba9845', 70 | amount: '10000000000000000000' 71 | } 72 | 73 | */ 74 | 75 | ``` 76 | -------------------------------------------------------------------------------- /libs/transfer/transfer-tokens.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3') 2 | const Big = require('big.js') 3 | const fromExponential = require('from-exponential') 4 | 5 | module.exports.transferTokens = async function ({ 6 | fromAddress, 7 | toAddress, 8 | amount, 9 | tokenSmartContractAddress = null, 10 | tokenSmartContractAbi = null, 11 | provider, 12 | walletPassword, 13 | encryptedPrivateKey, 14 | max = false, 15 | token = false, 16 | network = null, 17 | }) { 18 | const web3 = new Web3(provider) 19 | if (!web3.utils.isAddress(fromAddress)) { 20 | throw Error('The sender address is not a valid ethereum address !!') 21 | } 22 | 23 | if (!web3.utils.isAddress(toAddress)) { 24 | throw Error('The recipient address is not a valid ethereum address !!') 25 | } 26 | 27 | let tokenSmartContract = null 28 | 29 | if (tokenSmartContractAddress !== null) { 30 | tokenSmartContract = new web3.eth.Contract( 31 | tokenSmartContractAbi, 32 | tokenSmartContractAddress 33 | ) 34 | } 35 | 36 | const senderBalance = 37 | tokenSmartContractAddress === null 38 | ? await web3.eth.getBalance(fromAddress) 39 | : await tokenSmartContract.methods.balanceOf(fromAddress).call() 40 | 41 | if (new Big(amount).gt(new Big(senderBalance)) && max === 'flase') { 42 | throw Error('No enough balance to perform withdraw !!') 43 | } 44 | 45 | const gasPrice = await web3.eth.getGasPrice() 46 | if (max === 'true') amount = senderBalance 47 | 48 | let gasLimit = 49 | tokenSmartContractAddress === null 50 | ? await web3.eth.estimateGas({ to: toAddress }) 51 | : await tokenSmartContract.methods 52 | .transfer(toAddress, amount) 53 | .estimateGas({ from: fromAddress }) 54 | 55 | web3.eth.accounts.wallet.decrypt([encryptedPrivateKey], walletPassword) 56 | 57 | try { 58 | let result 59 | if ( 60 | tokenSmartContractAddress === null || 61 | tokenSmartContractAddress === process.env.TOKEN_BTT_CONTRACT 62 | ) { 63 | token && (gasLimit = 21000) 64 | if (max == 'true') 65 | amount = new Big(senderBalance).minus( 66 | new Big(gasLimit).times(new Big(gasPrice)) 67 | ) 68 | 69 | result = await web3.eth.sendTransaction({ 70 | from: fromAddress, 71 | to: toAddress, 72 | value: fromExponential(amount), 73 | gas: gasLimit, 74 | gasPrice, 75 | }) 76 | } else { 77 | gasLimit = network === 'BEP20' ? 21000 : 65000 78 | result = await tokenSmartContract.methods 79 | .transfer(toAddress, fromExponential(amount)) 80 | .send({ 81 | from: fromAddress, 82 | gas: gasLimit, 83 | gasPrice, 84 | }) 85 | } 86 | 87 | return { 88 | blockHash: result.blockHash, 89 | blockNumber: result.blockNumber, 90 | transactionHash: result.transactionHash, 91 | from: fromAddress, 92 | to: toAddress, 93 | amount: amount, 94 | } 95 | } catch (error) { 96 | return { error: error.message } 97 | } finally { 98 | web3.eth.accounts.wallet.remove(fromAddress) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /conf/fullchain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFMzCCBBugAwIBAgISBK4Pb3r06tIFL5JD3T/2+GEoMA0GCSqGSIb3DQEBCwUA 3 | MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD 4 | EwJSMzAeFw0yMTAxMjQwODEzNTBaFw0yMTA0MjQwODEzNTBaMCExHzAdBgNVBAMT 5 | FndhbGxldC5pZnJhbWUtYXBwcy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 6 | ggEKAoIBAQDddRovkVrrL0BXpGEi3LbN/CKBNmyWn5/PF4SNER4FAH/n+HKO6FfH 7 | uB+Y0smOmNlDhYhBku2xOYwnmEYlDh7H/DPkWdJ3GNil5n5mHloLfXSzkanRxlYF 8 | RA8dLSJM1fqVbotQEfuP21u56OxDbYICU7SCFgPl41f7etXP5MxXFtgPTgjVJTaR 9 | bhAPWuwTC0dH0EzpY0HfdB6f8wWwbkvQP6HjMjaH8BWwYAL1jZ1Y6cm9r49qEynI 10 | cr/gnFfkgcgJiaj5uPpZr2sqWm0Teex1aTrzF/aci+Dkdz/d41hnC34jlUB4y4as 11 | pbz4aikfP5jj8sQeVJHjgZwR5Sf7dUfBAgMBAAGjggJSMIICTjAOBgNVHQ8BAf8E 12 | BAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQC 13 | MAAwHQYDVR0OBBYEFNsU5fxGivFbV9QlBk6M4dzu0g+AMB8GA1UdIwQYMBaAFBQu 14 | sxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYV 15 | aHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5s 16 | ZW5jci5vcmcvMCEGA1UdEQQaMBiCFndhbGxldC5pZnJhbWUtYXBwcy5jb20wTAYD 17 | VR0gBEUwQzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYa 18 | aHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEFBgorBgEEAdZ5AgQCBIH2BIHz 19 | APEAdgBc3EOS/uarRUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAXczq8NGAAAE 20 | AwBHMEUCIQCANdfxwn2mkxRilTdVThw8cKdwzsn2tiEpa7s5Bwmq0wIgdCueSgf8 21 | rW9UkPl5KdwzdvhYAP3Bb4lzywbaQvnGPm0AdwD2XJQv0XcwIhRUGAgwlFaO400T 22 | GTO/3wwvIAvMTvFk4wAAAXczq8M6AAAEAwBIMEYCIQCatfWTjBc83uDE2+d3yQOK 23 | CnEJoIJ6+imH8KlXj5/c7gIhAPZgu7KLe7j1tFiOrr7Y28oZ94QaWrTLGrRf3JdQ 24 | ymxqMA0GCSqGSIb3DQEBCwUAA4IBAQAXQBX+UEqwWwGwoJ9u39dHZEgnyejXEnzZ 25 | D7oAym4awIP+CMfKq9peTeG5wI9vBPviSBOymrr/MXcaMJKbUP5JU1nY3aN3dmzz 26 | AJ9d+VHbe5VtJNd/+5WWpXOf2YHHWmyCFDJbJfp4qMbubra/AUbVLEDGuZsCrTTK 27 | R654NOlSJmKFtvV1aLNpwfT3XDAfIG2Y5OjIjgmtpMx1cONQl42sizIJAHb9TYjt 28 | bteQmkI5IgjHmqR2aUHTN21hkgnoyblgH9DZCZE82QWUZAMyf1yRzCX1GN/Nfs6l 29 | BzaGxvsCCl235lj73cQV0TSuoZy2jAjRrtQxvX5Jm3L+GUBbAKGN 30 | -----END CERTIFICATE----- 31 | -----BEGIN CERTIFICATE----- 32 | MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/ 33 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 34 | DkRTVCBSb290IENBIFgzMB4XDTIwMTAwNzE5MjE0MFoXDTIxMDkyOTE5MjE0MFow 35 | MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT 36 | AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs 37 | jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp 38 | Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB 39 | U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7 40 | gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel 41 | /xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R 42 | oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E 43 | BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p 44 | ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE 45 | p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE 46 | AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu 47 | Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0 48 | LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf 49 | r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B 50 | AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH 51 | ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8 52 | S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL 53 | qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p 54 | O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw 55 | UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg== 56 | -----END CERTIFICATE----- 57 | -------------------------------------------------------------------------------- /public/tron-icon.svg: -------------------------------------------------------------------------------- 1 | <svg width="138" height="140" viewBox="0 0 138 140" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <circle cx="68.895" cy="68.895" r="68.895" fill="#00041B"/> 3 | <g filter="url(#filter0_df_7057_60676)"> 4 | <path d="M109.858 56.627C105.715 52.8016 99.9848 46.9599 95.316 42.8174L95.0406 42.6239C94.5807 42.2552 94.0624 41.966 93.507 41.7682C82.2453 39.67 29.8721 29.8774 28.8508 30.0012C28.5629 30.0409 28.2876 30.1451 28.0457 30.3061L27.7877 30.5135C27.4641 30.8408 27.2186 31.2369 27.0697 31.6725L27 31.8467V32.9795C32.8975 49.405 56.1807 103.197 60.7641 115.816C61.0412 116.672 61.5658 118.301 62.547 118.385H62.7666C63.2894 118.385 65.5288 115.422 65.5288 115.422C65.5288 115.422 105.522 66.9301 109.568 61.7646C110.092 61.1287 110.555 60.4442 110.948 59.7204C111.049 59.1544 111.002 58.572 110.81 58.0299C110.619 57.4878 110.291 57.0045 109.858 56.627ZM75.7971 62.2752L92.8587 48.1258L102.871 57.3502L75.7971 62.2752ZM69.1747 61.3498L39.7744 37.2667L87.3202 46.0345L69.1747 61.3498ZM71.8271 67.6621L101.904 62.8137L67.5034 104.243L71.8271 67.6621ZM35.7835 39.67L66.7034 65.9019L62.228 104.27L35.7835 39.67Z" fill="white"/> 5 | </g> 6 | <g filter="url(#filter1_d_7057_60676)"> 7 | <path d="M109.858 56.627C105.715 52.8016 99.9848 46.9599 95.316 42.8174L95.0406 42.6239C94.5807 42.2552 94.0624 41.966 93.507 41.7682C82.2453 39.67 29.8721 29.8774 28.8508 30.0012C28.5629 30.0409 28.2876 30.1451 28.0457 30.3061L27.7877 30.5135C27.4641 30.8408 27.2186 31.2369 27.0697 31.6725L27 31.8467V32.9795C32.8975 49.405 56.1807 103.197 60.7641 115.816C61.0412 116.672 61.5658 118.301 62.547 118.385H62.7666C63.2894 118.385 65.5288 115.422 65.5288 115.422C65.5288 115.422 105.522 66.9301 109.568 61.7646C110.092 61.1287 110.555 60.4442 110.948 59.7204C111.049 59.1544 111.002 58.572 110.81 58.0299C110.619 57.4878 110.291 57.0045 109.858 56.627ZM75.7971 62.2752L92.8587 48.1258L102.871 57.3502L75.7971 62.2752ZM69.1747 61.3498L39.7744 37.2667L87.3202 46.0345L69.1747 61.3498ZM71.8271 67.6621L101.904 62.8137L67.5034 104.243L71.8271 67.6621ZM35.7835 39.67L66.7034 65.9019L62.228 104.27L35.7835 39.67Z" fill="white"/> 8 | </g> 9 | <defs> 10 | <filter id="filter0_df_7057_60676" x="8" y="11" width="122" height="126.385" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> 11 | <feFlood flood-opacity="0" result="BackgroundImageFix"/> 12 | <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> 13 | <feOffset dy="4"/> 14 | <feGaussianBlur stdDeviation="2"/> 15 | <feComposite in2="hardAlpha" operator="out"/> 16 | <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> 17 | <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7057_60676"/> 18 | <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7057_60676" result="shape"/> 19 | <feGaussianBlur stdDeviation="9.5" result="effect2_foregroundBlur_7057_60676"/> 20 | </filter> 21 | <filter id="filter1_d_7057_60676" x="5" y="7" width="128" height="132.385" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> 22 | <feFlood flood-opacity="0" result="BackgroundImageFix"/> 23 | <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> 24 | <feOffset dy="-1"/> 25 | <feGaussianBlur stdDeviation="11"/> 26 | <feComposite in2="hardAlpha" operator="out"/> 27 | <feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/> 28 | <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_7057_60676"/> 29 | <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_7057_60676" result="shape"/> 30 | </filter> 31 | </defs> 32 | </svg> 33 | -------------------------------------------------------------------------------- /contracts/SattResolver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5; 2 | 3 | contract owned { 4 | address payable public owner; 5 | 6 | constructor () public { 7 | owner = msg.sender; 8 | } 9 | 10 | modifier onlyOwner { 11 | require(msg.sender == owner); 12 | _; 13 | } 14 | 15 | function transferOwnership(address payable newOwner) onlyOwner public { 16 | owner = newOwner; 17 | } 18 | } 19 | 20 | contract SattResolver is owned { 21 | 22 | struct PublicKey { 23 | bytes32 x; 24 | bytes32 y; 25 | } 26 | 27 | mapping(bytes32=>address) addresses; 28 | mapping(bytes32=>string) names; 29 | mapping(bytes32=>mapping(uint256=>bytes)) abis; 30 | mapping(bytes32=>bytes) hashes; 31 | mapping(bytes32=>PublicKey) pubkeys; 32 | mapping(bytes32=>mapping(string=>string)) texts; 33 | 34 | event AddrChanged(bytes32 indexed node, address a); 35 | event NameChanged(bytes32 indexed node, string name); 36 | event ContenthashChanged(bytes32 indexed node, bytes hash); 37 | event ABIChanged(bytes32 indexed node, uint256 indexed contentType); 38 | event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); 39 | event TextChanged(bytes32 indexed node, string indexedKey, string key); 40 | 41 | function supportsInterface(bytes4 interfaceID) public pure returns (bool) { 42 | return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7 || interfaceID == 0x691f3431 || interfaceID == 0x2203ab56 || interfaceID == 0xc8690233 || interfaceID == 0x59d1d43c || interfaceID == 0xbc1c58d1; 43 | } 44 | 45 | function addr(bytes32 node) external view returns (address) 46 | { 47 | return addresses[node]; 48 | } 49 | 50 | function setAddr(bytes32 node, address ad) external onlyOwner { 51 | addresses[node] = ad; 52 | emit AddrChanged(node, ad); 53 | } 54 | 55 | function name(bytes32 node) external view returns (string memory) { 56 | return names[node]; 57 | } 58 | 59 | function setName(bytes32 node, string calldata nme) external onlyOwner { 60 | emit NameChanged(node, nme); 61 | } 62 | 63 | function contenthash(bytes32 node) external view returns (bytes memory) { 64 | return hashes[node]; 65 | } 66 | 67 | function setContenthash(bytes32 node, bytes calldata hash) external onlyOwner { 68 | hashes[node] = hash; 69 | emit ContenthashChanged(node, hash); 70 | } 71 | 72 | function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory) { 73 | mapping(uint256=>bytes) storage abiset = abis[node]; 74 | 75 | for (uint256 contentType = 1; contentType <= contentTypes; contentType <<= 1) { 76 | if ((contentType & contentTypes) != 0 && abiset[contentType].length > 0) { 77 | return (contentType, abiset[contentType]); 78 | } 79 | } 80 | 81 | return (0, bytes("")); 82 | } 83 | 84 | function setABI(bytes32 node, uint256 contentType, bytes calldata data) external onlyOwner { 85 | require(((contentType - 1) & contentType) == 0); 86 | 87 | abis[node][contentType] = data; 88 | emit ABIChanged(node, contentType); 89 | } 90 | 91 | function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) { 92 | return (pubkeys[node].x, pubkeys[node].y); 93 | } 94 | 95 | function setPubkey(bytes32 node, bytes32 x, bytes32 y) external onlyOwner { 96 | pubkeys[node] = PublicKey(x, y); 97 | emit PubkeyChanged(node, x, y); 98 | } 99 | 100 | function text(bytes32 node, string calldata key) external view returns (string memory) { 101 | return texts[node][key]; 102 | } 103 | 104 | function setText(bytes32 node, string calldata key, string calldata value) external onlyOwner { 105 | texts[node][key] = value; 106 | emit TextChanged(node, key, key); 107 | } 108 | } -------------------------------------------------------------------------------- /model/user.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | autoIncrement = require('mongoose-auto-increment') 4 | const { mongoConnection } = require('../conf/config') 5 | 6 | const db = mongoose.createConnection(mongoConnection(), { 7 | useNewUrlParser: true, 8 | useUnifiedTopology: true, 9 | useCreateIndex: true, 10 | useFindAndModify: false, 11 | }) 12 | autoIncrement.initialize(db) 13 | const userSchema = mongoose.Schema( 14 | { 15 | first_name: { type: String }, 16 | name: { type: String }, 17 | idSn: { type: Number, default: 0 }, 18 | idOnSn: { type: String }, 19 | idOnSn2: { type: String }, 20 | idOnSn3: { type: String }, 21 | created: { type: Date, default: Date.now }, 22 | email: { type: String, unique: true }, 23 | username: { type: String }, 24 | firstName: { type: String }, 25 | lastName: { type: String }, 26 | lastLogin: { type: Date, default: Date.now }, 27 | newsLetter: { type: Boolean }, 28 | onBoarding: { type: Boolean, default: false }, 29 | account_locked: { type: Boolean, default: 0 }, 30 | failed_count: { type: Number, default: 0 }, 31 | date_locked: { type: Number }, 32 | enabled: { type: Number }, 33 | locale: { type: String, default: 'en' }, 34 | userSatt: { type: Boolean, default: true }, 35 | picLink: { type: String }, 36 | dateFirstAttempt: { type: Number }, 37 | completed: { type: Boolean, default: false }, 38 | password: { type: String }, 39 | lastHarvestDate: { type: mongoose.Schema.Types.Mixed }, 40 | 41 | secureCode: { 42 | code: { type: Number }, 43 | expiring: { type: Number }, 44 | type: { type: String }, 45 | attempts: { type: Number, default: 0 }, 46 | lastTry: { type: Number }, 47 | }, 48 | newEmail: { 49 | email: { type: String }, 50 | expiring: { type: Number }, 51 | code: { type: Number }, 52 | }, 53 | hasWallet: { type: Boolean, default: false }, 54 | hasWalletV2: { type: Boolean, default: false }, 55 | migrated:{ type: Boolean, default: false }, 56 | passphrase: { type: Boolean, default: false }, 57 | is2FA: { type: Boolean, default: false }, 58 | hasBiometrics: { type: Boolean, default: false }, 59 | secret: { type: String }, 60 | photoUpdated: { type: Boolean, default: false }, 61 | isChanged: { type: Boolean, default: false }, 62 | birthday: { type: String }, 63 | gender: { type: String }, 64 | daily: [ 65 | { 66 | Date: { type: Number }, 67 | Balance: { type: String }, 68 | convertDate: { type: String }, 69 | }, 70 | ], 71 | weekly: [ 72 | { 73 | Date: { type: Number }, 74 | Balance: { type: String }, 75 | convertDate: { type: String }, 76 | }, 77 | ], 78 | monthly: [ 79 | { 80 | Date: { type: Number }, 81 | Balance: { type: String }, 82 | convertDate: { type: String }, 83 | }, 84 | ], 85 | address: { type: String }, 86 | city: { type: String }, 87 | country: { type: String }, 88 | zipCode: { type: String }, 89 | visitPassphrase: { type: Boolean, default: false }, 90 | fireBaseAccessToken: { type: String }, 91 | fireBaseAccessTokenMObile: { type: String }, 92 | 93 | phone: { 94 | number: { type: String }, 95 | internationalNumber: { type: String }, 96 | nationalNumber: { type: String }, 97 | e164Number: { type: String }, 98 | countryCode: { type: String }, 99 | dialCode: { type: String }, 100 | }, 101 | }, 102 | { timestamps: true, strict: false, collection: 'user' } 103 | ) 104 | userSchema.plugin(autoIncrement.plugin, { 105 | model: 'user', 106 | field: '_id', 107 | startAt: 100, 108 | incrementBy: 1, 109 | }) 110 | const User = db.model('user', userSchema) 111 | module.exports = User 112 | -------------------------------------------------------------------------------- /public/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": "Welcome !", 3 | "finished_inscription": "Your registration is almost complete! <br> You just have to validate your email to access all the services offered by SaTT.", 4 | "validate_mail": "I confirm my email", 5 | "contact_support": "If you did not initiate this registration,<br> please contact the technical support.", 6 | "create_portfolio": "Say ‘hello’ to your new wallet", 7 | "create_secure": "Create an easily accessible and secure wallet <br>Select a strong password that you’ll remember<br> Of note, we are unable to help recover lost passwords.", 8 | "monetisez": "Monetization made easy", 9 | "monetisez_description": "Whether you’re new to the social media landscape or are an established influencer, your audience size translates directly into your earnings. The SaTT platform leverages blockchain to automate your payments with uncompromising accuracy, every time.", 10 | "automate_campaign": " Ad Pool Revolution, a new and easy way to promote brands", 11 | "automate_campaign_description": "Anyone can quickly create an Advertising Pool and allow influencers from all over the world to promote their brands. Set the appropriate budget without a middleman for a much cheaper price and ensure that you’re getting the most bang for your buck.", 12 | "questions": "Questions ? Ask away!", 13 | "questions_description": "We’re here to support you! Our dedicated support staff is always within reach via our social platforms. Let’s find answers, together. ", 14 | "consult_faq": "Consult the FAQ", 15 | "reset_pass 1": "Reset your login password", 16 | "new_pass": "New password", 17 | "ask_pass": "You asked to reset your login password", 18 | "connex": "to dapp.satt.com", 19 | "valid_mess": "Your link for the ", 20 | "reject_trans": "Unfortunately, the advertiser rejected your", 21 | "link_w": "link.", 22 | "link_added": "New link alert ! 🎉", 23 | "valid_contact": "contact us", 24 | "reject_questions": "Questions ! Don't be shy ! we're here to help.", 25 | "reject_reason": "Here’s what they said...", 26 | "reject_link": "Rejected link 😧", 27 | "valid_need": "If you have any question", 28 | "valid_wish": "From our SaTT family to yours, we wish you all the best !", 29 | "valid_accepted": "campaign link was just validated by the advertiser. It’s high time to celebrate !", 30 | "reject_cmp": "campaign has been rejected by the advertiser.", 31 | "valid_question": "Ready to collect your earnings ?", 32 | "valid_gaz": "Your hard-earned SaTT is ready for you to claim. At the same time, don’t forget thatyou need to verify if you have Ethereum or Binance Coin in your wallet. In order to interface with the blockchain, you need to verify this first.", 33 | "valid_post": "Get posting !", 34 | "link": "Click on the link below to reset it", 35 | "reset_pass2": "Reset your password", 36 | "reset_pass3": "If you did not make this request, ignore this Email", 37 | "contact": "Contact us", 38 | "about": "About SaTT", 39 | "insert-question": "Questions or concerns? We’re just a message away!", 40 | "new_link": "Say ‘hello’ to your campaign’s newest link :", 41 | "new_link_added": "has been added", 42 | "new_link_campaign": "The world is your oyster.", 43 | "Hello": "Hello", 44 | "link_valid": "Congratulations ! 🍾", 45 | "link_trans": "Your", 46 | "Bonjour": "Bonjour", 47 | "ask_to_send": "is requesting", 48 | "here_is_message": "message to you", 49 | "here_is_the_message": "Here is the message:", 50 | "wallet_of": "wallet is", 51 | "is": "is", 52 | "cmp_link": "cmp_link", 53 | "Support": "Contact customer service.", 54 | "cmp_title": "cmp_title", 55 | "changement_email_presque_terminé": "You’re just steps away from changing your email address...", 56 | "validation_code": "Your verification code is :", 57 | "code-expire": "Please submit your code within the next 5 minutes. Afterward, the code will be void.", 58 | "code-request": "Didn’t request to change your email ?", 59 | "time-request": "Request time", 60 | "Location": "Location", 61 | "request-done": "has been requested.", 62 | "request": "A request to reset your", 63 | "mail": "E-mail adress", 64 | "verif-code": "Email reset request", 65 | "send-money": "Fulfill request" 66 | } 67 | -------------------------------------------------------------------------------- /public/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": "bienvenue !", 3 | "finished_inscription": "Votre inscription est presque terminée ! <br>Il ne vous reste plus qu’à valider votre mail pour accéder à <br> tous les services proposés par SaTT. ", 4 | "validate_mail": "Je valide mon mail", 5 | "contact_support": "Si vous n'êtes pas à l'origine de cette inscription, <br>veuillez contacter le support.", 6 | "create_portfolio": "Créer votre portefeuille !", 7 | "create_secure": "Créez et sécurisez votre portefeuille !<br> Choisissez et notez vos mots de passe avec précaution.<br> Nous ne pouvons pas vous aider à le retrouver en cas de perte.", 8 | "monetisez": "Monétisez votre audience !", 9 | "monetisez_description": "Que vous ayez 50 abonnés ou 1 million de followers, soyez rémunéré à la hauteur de votre audience. La plateforme Satturn est conçue dans le but de convenir au plus grand nombre. Grâce à la blockchain, soyez sûr d’être rémunéré, tout est automatisé.", 10 | "automate_campaign": "Concevez, paramétrez, automatisez votre campagne. ", 11 | "automate_campaign_description": "Choisissez parmi les influencers du monde entier, les petits ou les plus grands.Planifiez votre budget sans intermédiaire ni négociation. Ayez le contrôle sur votre campagne, faites en un chef-d'œuvre à votre image.Étudiez vos statistiques et recommencez. <br>Profitez de frais compétitifs.<br>Vous avez toutes les clés en main pour faire de votre campagne un succès !", 12 | "questions": "Vous avez des questions ?", 13 | "questions_description": "Toute notre équipe support est disponible <br>pour répondre à chacune de vos questions.<br>N'hésitez pas à les contacter via nos différents réseaux sociaux !", 14 | "consult_faq": "Consultez la FAQ", 15 | "reset_pass1": "", 16 | "ask_pass": "Vous avez demandé à renouveler votre mot de passe", 17 | "connex": "de connexion au site dapp.satt.com.", 18 | "link": "Cliquez sur le lien ci-dessous pour réinitialiser votre nouveau mot de passe de connexion", 19 | "reset_pass2": "Réinitialiser le mot de passe", 20 | "reset_pass3": "Si vous n'êtes pas à l'origine de cette demande, veuillez ignorez cet Email", 21 | "link_w": "lien.", 22 | "contact": "Nous contacter", 23 | "link_added": "Alerte nouveau lien ! 🎉", 24 | "insert-question": "Questions ou préoccupations? Nous ne sommes qu'à un message !", 25 | "reject_questions": "Des questions ! Ne soyez pas timide ! nous sommes là pour vous aider.", 26 | "reject_reason": "Voici ce qu'ils ont dit...", 27 | "reject_link": "Lien rejeté...", 28 | "valid_mess": "Votre lien pour la campagne", 29 | "new_link": "Dites « bonjour » au dernier lien de votre campagne :", 30 | "new_link_campaign": "Le monde est ton coquillage.", 31 | "new_link_added": "a été ajouté", 32 | "reject_cmp": "a été rejeté par l'annonceur !", 33 | "valid_accepted": "le lien de campagne vient d'être validé par l'annonceur. Il est grand temps de célébrer !", 34 | "valid_question": "Prêt à récolter vos gains ?", 35 | "valid_contact": "nous contactez", 36 | "valid_wish": "De la part de notre famille SaTT à la vôtre, nous vous souhaitons tout le meilleur !", 37 | "valid_need": "En cas de question, n'hésitez pas à", 38 | "valid_gaz": "vous pouvez récolter vos gains à tout moment, mais n'oubliez pas que chaque transaction coûte du gaz ! Pensez à vérifier que vous possédez des Ethereum (ERC20 et/ou) des Binance Coin(BEP20)", 39 | "about": "À propos de SaTT", 40 | "valid_post": "Poster un autre lien", 41 | "Hello": "Bonjour", 42 | "reject_trans": "Malheureusement, l'annonceur a rejeté votre", 43 | "link_valid": "Lien Validé ! 🍾", 44 | "link_trans": "Votre", 45 | "Bonjour": "Bonjour", 46 | "new_pass": "Nouveau password", 47 | "ask_to_send": "Vous demande de lui envoyer", 48 | "here_is_message": "Voici son message", 49 | "wallet_of": "la portefeuille de", 50 | "is": "est", 51 | "changement_email_presque_terminé": "Votre demande de changement <br> d'adresse email est presque terminée !", 52 | "validation_code": "Votre code de validation", 53 | "code-expire": "Ce code de vérification ne sera valable que 5 minutes", 54 | "code-request": "Vous n'avez pas demandé de modifier votre email ?", 55 | "Support": "Contactez le support.", 56 | "time-request": "Moment de la requête", 57 | "Location": "Localisation", 58 | "request-done": "a été faite.", 59 | "request": "Une demande de réinitialisation de votre", 60 | "mail": "adresse Mail", 61 | "verif-code": "Code de vérification", 62 | "send-money": "Envoyer la somme" 63 | } 64 | -------------------------------------------------------------------------------- /routes/external.routes.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router() 3 | 4 | const { 5 | createUserFromExternalWallet, 6 | externalSocialAccounts, 7 | externalDeleteTiktokChannel, 8 | externalDeleteTiktokChannels, 9 | externalDeleteGoogleChannel, 10 | externalDeleteGoogleChannels, 11 | externalDeleteFacebookChannels, 12 | externalDeleteFacebookChannel, 13 | externalDeleteLinkedinChannels, 14 | externalDeleteLinkedinChannel, 15 | externalDeleteTwitterChannels, 16 | externalDeleteTwitterChannel, 17 | externalVerifyLink, 18 | externalSaveCampaign, 19 | externalVerifyExpiredToken, 20 | externalAccount, 21 | externalUploadPictureToIPFS, 22 | campaignsPictureUploadExternal, 23 | externalAddKits, 24 | uploadExternal, 25 | externalGetLinks, 26 | externalGetOneLinks, 27 | externalApply, 28 | checkHarvest, 29 | externalAnswer, 30 | externalGains, 31 | campaigns, 32 | getBalanceUserExternal, 33 | externalDeleteDraft, 34 | } = require('../controllers/external.controller') 35 | const { verifyAuthExternal } = require('../middleware/passport.middleware') 36 | const { 37 | verifySignatureMiddleware, 38 | idCheckValidation, 39 | addKitsValidation, 40 | externalGainsValidation, 41 | } = require('./../middleware/verifySignature.middleware') 42 | const multer = require('multer') 43 | 44 | const storage = multer.diskStorage({ 45 | destination: function (req, file, cb) { 46 | cb(null, 'uploads/') // Uploads directory 47 | }, 48 | filename: function (req, file, cb) { 49 | cb(null, Date.now() + '-' + file.originalname) 50 | }, 51 | }) 52 | const upload = multer({ storage: storage }) 53 | 54 | router.post('/create-user', createUserFromExternalWallet) 55 | router.get('/campaigns', campaigns) 56 | router.post('/getBalance', getBalanceUserExternal) 57 | router.post('/createCampaign', verifyAuthExternal, externalSaveCampaign) 58 | // DONE 59 | router.get('/socialAccounts', verifyAuthExternal, externalSocialAccounts) 60 | router.post( 61 | '/campaign/filterLinksExternal', 62 | verifyAuthExternal, 63 | externalGetLinks 64 | ) 65 | 66 | router.delete( 67 | '/deleteDraft/:id', 68 | verifyAuthExternal, 69 | idCheckValidation, 70 | externalDeleteDraft 71 | ) 72 | router.post( 73 | '/campaign/getLinksExternal', 74 | verifyAuthExternal, 75 | externalGetOneLinks 76 | ) 77 | 78 | // DONE 79 | 80 | router.get('/verify-token', verifyAuthExternal, externalVerifyExpiredToken) 81 | router.get('/externalAccount', verifyAuthExternal, externalAccount) 82 | 83 | // DONE 84 | router.delete( 85 | '/RemoveTiktokChannel/:id', 86 | verifyAuthExternal, 87 | externalDeleteTiktokChannel 88 | ) 89 | 90 | router.delete( 91 | '/RemoveTiktokChannels', 92 | verifyAuthExternal, 93 | externalDeleteTiktokChannels 94 | ) 95 | 96 | router.delete( 97 | '/RemoveGoogleChannel/:id', 98 | verifyAuthExternal, 99 | externalDeleteGoogleChannel 100 | ) 101 | 102 | router.delete( 103 | '/RemoveGoogleChannels', 104 | verifyAuthExternal, 105 | externalDeleteGoogleChannels 106 | ) 107 | 108 | router.delete( 109 | '/RemoveFacebookChannels', 110 | verifyAuthExternal, 111 | externalDeleteFacebookChannels 112 | ) 113 | 114 | router.delete( 115 | '/RemoveFacebookChannel/:id', 116 | verifyAuthExternal, 117 | externalDeleteFacebookChannel 118 | ) 119 | 120 | router.delete( 121 | '/RemoveLinkedInChannels', 122 | verifyAuthExternal, 123 | externalDeleteLinkedinChannels 124 | ) 125 | 126 | router.delete( 127 | '/remove/:linkedinId/linkedInChannel/:organization', 128 | verifyAuthExternal, 129 | externalDeleteLinkedinChannel 130 | ) 131 | 132 | router.delete( 133 | '/RemoveTwitterChannels', 134 | verifyAuthExternal, 135 | externalDeleteTwitterChannels 136 | ) 137 | 138 | router.delete( 139 | '/RemoveTwitterChannel/:id', 140 | verifyAuthExternal, 141 | externalDeleteTwitterChannel 142 | ) 143 | 144 | router.get( 145 | '/link/verify/:typeSN/:idUser/:idPost', 146 | verifyAuthExternal, 147 | externalVerifyLink 148 | ) 149 | 150 | router.post( 151 | '/externalUploadPictureToIPFS/:id', 152 | idCheckValidation, 153 | campaignsPictureUploadExternal, 154 | externalUploadPictureToIPFS 155 | ) 156 | 157 | router.post( 158 | '/externalAddKits', 159 | addKitsValidation, 160 | upload.single('file'), 161 | externalAddKits 162 | ) 163 | 164 | router.post('/apply', verifyAuthExternal, externalApply) 165 | 166 | router.post('/checkHarvest', verifyAuthExternal, checkHarvest) 167 | 168 | router.post('/externalAnswer', verifyAuthExternal, externalAnswer) 169 | router.post('/externalGains', verifyAuthExternal, externalGains) 170 | 171 | module.exports = router 172 | -------------------------------------------------------------------------------- /middleware/authValidator.middleware.js: -------------------------------------------------------------------------------- 1 | const Joi = require('joi'); 2 | 3 | 4 | /********** 5 | * 6 | * SCHEMA FOR JOI 7 | * 8 | * ********************** */ 9 | 10 | // VALIDATION TRANSACTION PASSWORD 11 | const validatePassword = () => Joi.string().min(8).required().custom((value) => { 12 | const RegUpperCase = RegExp('[A-Z]'); 13 | const RegLowerCase = RegExp('[a-z]'); 14 | const RegNumber = RegExp('[0-9]'); 15 | const RegSpecialChar = RegExp('[^A-Za-z0-9]'); 16 | if(RegUpperCase.test(value) && RegLowerCase.test(value) && RegNumber.test(value) && RegSpecialChar.test(value)) { 17 | return value; 18 | } else throw Error('password not match') 19 | }); 20 | 21 | 22 | // VALIDATION EMAIL 23 | const validateEmail = () => Joi.string().email({ tlds: { allow: false } }).regex(/^[^@]+@[^@]+\.[^@]+$/).required() 24 | 25 | 26 | 27 | 28 | 29 | // SCHEMAS OBJECT 30 | const schemas = { 31 | purgeAccountSchema: Joi.object({ 32 | password: validatePassword(), 33 | reason: Joi.string() 34 | }), 35 | 36 | changePasswordSchema: Joi.object({ 37 | newpass: validatePassword(), 38 | oldpass: validatePassword() 39 | }), 40 | 41 | emailConnectionSchema: Joi.object({ 42 | username: validateEmail(), 43 | password: validatePassword() 44 | }), 45 | 46 | codeRecoverSchema: Joi.object({ 47 | mail: validateEmail(), 48 | lang: Joi.string() 49 | }), 50 | 51 | confirmCodeSchema: Joi.object({ 52 | code: Joi.number().required(), 53 | email: validateEmail(), 54 | type: Joi.string().required().custom((value) => { 55 | if(value === "reset" || value === "validation") return value; 56 | else throw Error("Type must be 'reset'") 57 | }) 58 | }), 59 | 60 | passRecoverSchema: Joi.object({ 61 | newpass: validatePassword(), 62 | email: validateEmail(), 63 | code: Joi.number().required() 64 | }), 65 | 66 | emailSignupSchema: Joi.object({ 67 | password: validatePassword(), 68 | username: validateEmail(), 69 | lang: Joi.string(), 70 | newsLetter: Joi.boolean() 71 | }), 72 | 73 | resendConfirmationTokenSchema: Joi.object({ 74 | email: validateEmail(), 75 | lang: Joi.string() 76 | }), 77 | 78 | authAppleSchema: Joi.object({ 79 | id_apple: Joi.string().required(), 80 | mail: Joi.string().email({ tlds: { allow: false } }).regex(/^[^@]+@[^@]+\.[^@]+$/), 81 | idSN: Joi.number().required(), 82 | name: Joi.string() 83 | }), 84 | 85 | logoutSchema: Joi.object({ 86 | idUser: Joi.number().required(), 87 | }), 88 | 89 | setVisitSignUpStepSchema: Joi.object({ 90 | userId: Joi.number().required(), 91 | visitedStep: Joi.string().required() 92 | }), 93 | 94 | socialdisconnectSchema: Joi.object({ 95 | social: Joi.string().required(), 96 | }), 97 | 98 | saveFirebaseAccessTokenSchema: Joi.object({ 99 | fb_accesstoken: Joi.string().required() 100 | }), 101 | 102 | updateLastStepSchema: Joi.object({ 103 | completed: Joi.boolean().required(), 104 | email: validateEmail(), 105 | firstName: Joi.string(), 106 | lastName: Joi.string() 107 | }), 108 | 109 | verifyQrCodeSchema: Joi.object({ 110 | code: Joi.string().required(), 111 | }) 112 | } 113 | 114 | 115 | 116 | 117 | 118 | /********** 119 | * 120 | * MIDDLEWARE VALIDATION 121 | * 122 | * ********************** */ 123 | 124 | 125 | // MIDDLEWARE FUNCTION 126 | const validationMiddleware = (schema, property) => (req, res, next) => { 127 | const {error} = schema.validate(req[property]); 128 | if(error) throw Error(error); 129 | else next(); 130 | } 131 | 132 | 133 | 134 | 135 | 136 | module.exports = { 137 | purgeAccountValidation: validationMiddleware(schemas.purgeAccountSchema, 'body'), 138 | changePasswordValidation: validationMiddleware(schemas.changePasswordSchema, 'body'), 139 | emailConnectionValidation: validationMiddleware(schemas.emailConnectionSchema, 'body'), 140 | codeRecoverValidation: validationMiddleware(schemas.codeRecoverSchema, 'body'), 141 | confirmCodeValidation: validationMiddleware(schemas.confirmCodeSchema, 'body'), 142 | passRecovervalidation: validationMiddleware(schemas.passRecoverSchema, 'body'), 143 | emailSignupValidation: validationMiddleware(schemas.emailSignupSchema, 'body'), 144 | resendConfirmationTokenValidation: validationMiddleware(schemas.resendConfirmationTokenSchema, 'body'), 145 | authAppleValidation: validationMiddleware(schemas.authAppleSchema, 'body'), 146 | logoutValidation: validationMiddleware(schemas.logoutSchema, 'params'), 147 | setVisitSignUpStepValidation: validationMiddleware(schemas.setVisitSignUpStepSchema, 'body'), 148 | socialdisconnectValidation: validationMiddleware(schemas.socialdisconnectSchema, 'params'), 149 | saveFirebaseAccessTokenValidation: validationMiddleware(schemas.saveFirebaseAccessTokenSchema, 'body'), 150 | updateLastStepValidation: validationMiddleware(schemas.updateLastStepSchema, 'body'), 151 | verifyQrCodeValidation: validationMiddleware(schemas.verifyQrCodeSchema, 'body') 152 | }; -------------------------------------------------------------------------------- /manager/accounts.js: -------------------------------------------------------------------------------- 1 | const { Notification, User } = require('../model/index') 2 | 3 | const { sendNotification } = require('./notification') 4 | 5 | const { Tokens } = require('../conf/config') 6 | 7 | exports.notificationManager = async (id, NotifType, label) => { 8 | try { 9 | let notification = { 10 | idNode: '0' + id, 11 | type: NotifType, 12 | status: 'done', 13 | label, 14 | isSeen: false, 15 | isSend: false, 16 | attachedEls: { 17 | id: id, 18 | }, 19 | created: new Date(), 20 | } 21 | 22 | const notif = await Notification.create(notification) 23 | let user = await User.findOne({ _id: +id }).select( 24 | 'fireBaseAccessToken ' 25 | ) 26 | if (user.fireBaseAccessToken) { 27 | let data = { 28 | message: { 29 | token: user.fireBaseAccessToken, 30 | data: { 31 | obj: JSON.stringify(notification), 32 | }, 33 | }, 34 | } 35 | await sendNotification(data) 36 | } 37 | } catch (error) { 38 | console.log('err', error) 39 | } 40 | } 41 | 42 | exports.manageTime = () => { 43 | var d = new Date() 44 | var date = d.getDate() 45 | var month = d.getMonth() + 1 46 | var year = d.getFullYear() 47 | var seconds = d.getSeconds() 48 | var minutes = d.getMinutes() 49 | var hour = d.getHours() 50 | return year + '-' + month + '-' + ' ' + hour + ':' + minutes + ':' + seconds 51 | } 52 | 53 | exports.differenceBetweenDates = (authDate, dateNow) => { 54 | return Math.ceil(Math.abs(dateNow * 1000 - authDate * 1000) / 60000) 55 | } 56 | 57 | exports.updateAndGenerateCode = async (_id, type) => { 58 | try { 59 | const code = Math.floor(100000 + Math.random() * 900000) 60 | let secureCode = {} 61 | ;(secureCode.code = code), 62 | (secureCode.expiring = Date.now() + 3600 * 20 * 5), 63 | (secureCode.type = type) 64 | await User.updateOne({ _id }, { $set: { secureCode } }) 65 | return code 66 | } catch (e) { 67 | reject({ message: e.message }) 68 | } 69 | } 70 | 71 | exports.isBlocked = async (user, isAuthAttempt = false) => { 72 | const currentTime = Math.floor(Date.now() / 1000) 73 | let [isBlocked, updateFields] = [false, {}] 74 | 75 | if (isAuthAttempt) { 76 | if ( 77 | user.account_locked && 78 | this.differenceBetweenDates(user.date_locked, currentTime) < 79 | process.env.lockedPeriod 80 | ) { 81 | // If the user is locked and the locked period hasn't passed yet, reset the failed attempts and keep the account locked 82 | updateFields.date_locked = currentTime 83 | updateFields.failed_count = 0 84 | isBlocked = true 85 | } else { 86 | // If the locked period has passed, unlock the account 87 | updateFields.failed_count = 0 88 | updateFields.account_locked = false 89 | isBlocked = false 90 | } 91 | } else { 92 | let failedAttempts = user.failed_count ? user.failed_count + 1 : 1 93 | updateFields.failed_count = failedAttempts 94 | 95 | if (failedAttempts === 1) { 96 | updateFields.dateFirstAttempt = currentTime 97 | } 98 | 99 | if (user.account_locked) { 100 | // If the user is already locked, reset the failed attempts and update the locked date 101 | updateFields.date_locked = currentTime 102 | updateFields.failed_count = 0 103 | isBlocked = true 104 | } else if ( 105 | !user.account_locked && 106 | failedAttempts >= process.env.bad_login_limit && 107 | this.differenceBetweenDates(user.dateFirstAttempt, currentTime) < 108 | process.env.failInterval 109 | ) { 110 | // If the user is not locked, and they've reached the limit of failed attempts in the given interval, lock the account 111 | updateFields.account_locked = true 112 | updateFields.failed_count = 0 113 | updateFields.date_locked = currentTime 114 | isBlocked = true 115 | } else if (failedAttempts >= process.env.bad_login_limit) { 116 | // If the user has reached the limit of failed attempts but not in the given interval, reset the failed attempts count 117 | updateFields.failed_count = 1 118 | } 119 | } 120 | // If there are any changes, update the user record in the database 121 | Object.keys(updateFields).length && 122 | (await User.updateOne({ _id: user._id }, { $set: updateFields })) 123 | 124 | return { res: isBlocked, blockedDate: currentTime, auth: isAuthAttempt } 125 | } 126 | exports.getDecimal = (symbol) => { 127 | try { 128 | let token_info = Tokens 129 | 130 | symbol = 131 | symbol === 'SATTBEP20' 132 | ? 'SATT_BEP20' 133 | : symbol === 'SATTBTT' 134 | ? 'SATT_BTT' 135 | : symbol 136 | 137 | return +token_info[symbol].dicimal 138 | } catch (err) {} 139 | } 140 | -------------------------------------------------------------------------------- /public/privacy.html: -------------------------------------------------------------------------------- 1 | <h1>Privacy Policy of Atayen</h1> 2 | 3 | <p> 4 | Atayen operates the https://wallet.iframe-apps.com:3014/ website, which 5 | provides the SERVICE. 6 | </p> 7 | 8 | <p> 9 | This page is used to inform website visitors regarding our policies with the 10 | collection, use, and disclosure of Personal Information if anyone decided to 11 | use our Service, the Atayen Oracle website. 12 | </p> 13 | 14 | <p> 15 | If you choose to use our Service, then you agree to the collection and use 16 | of information in relation with this policy. The Personal Information that 17 | we collect are used for providing and improving the Service. We will not use 18 | or share your information with anyone except as described in this Privacy 19 | Policy. 20 | </p> 21 | 22 | <p> 23 | The terms used in this Privacy Policy have the same meanings as in our Terms 24 | and Conditions, which is accessible at https://wallet.iframe-apps.com:3014/, 25 | unless otherwise defined in this Privacy Policy. Our Privacy Policy was 26 | created with the help of the 27 | <a href="https://www.privacypolicytemplate.net">Privacy Policy Template</a> 28 | and the 29 | <a href="https://www.privacy-policy-template.com/" 30 | >Online Privacy Policy Template</a 31 | >. 32 | </p> 33 | 34 | <h2>Information Collection and Use</h2> 35 | 36 | <p> 37 | For a better experience while using our Service, we may require you to 38 | provide us with certain personally identifiable information, including but 39 | not limited to your name, phone number, and postal address. The information 40 | that we collect will be used to contact or identify you. 41 | </p> 42 | 43 | <h2>Log Data</h2> 44 | 45 | <p> 46 | We want to inform you that whenever you visit our Service, we collect 47 | information that your browser sends to us that is called Log Data. This Log 48 | Data may include information such as your computer’s Internet Protocol 49 | ("IP") address, browser version, pages of our Service that you visit, the 50 | time and date of your visit, the time spent on those pages, and other 51 | statistics. 52 | </p> 53 | 54 | <h2>Cookies</h2> 55 | 56 | <p> 57 | Cookies are files with small amount of data that is commonly used an 58 | anonymous unique identifier. These are sent to your browser from the website 59 | that you visit and are stored on your computer’s hard drive. 60 | </p> 61 | 62 | <p> 63 | Our website uses these "cookies" to collection information and to improve 64 | our Service. You have the option to either accept or refuse these cookies, 65 | and know when a cookie is being sent to your computer. If you choose to 66 | refuse our cookies, you may not be able to use some portions of our Service. 67 | </p> 68 | 69 | <h2>Service Providers</h2> 70 | 71 | <p> 72 | We may employ third-party companies and individuals due to the following 73 | reasons: 74 | </p> 75 | 76 | <ul> 77 | <li>To facilitate our Service;</li> 78 | <li>To provide the Service on our behalf;</li> 79 | <li>To perform Service-related services; or</li> 80 | <li>To assist us in analyzing how our Service is used.</li> 81 | </ul> 82 | 83 | <p> 84 | We want to inform our Service users that these third parties have access to 85 | your Personal Information. The reason is to perform the tasks assigned to 86 | them on our behalf. However, they are obligated not to disclose or use the 87 | information for any other purpose. 88 | </p> 89 | 90 | <h2>Security</h2> 91 | 92 | <p> 93 | We value your trust in providing us your Personal Information, thus we are 94 | striving to use commercially acceptable means of protecting it. But remember 95 | that no method of transmission over the internet, or method of electronic 96 | storage is 100% secure and reliable, and we cannot guarantee its absolute 97 | security. 98 | </p> 99 | 100 | <h2>Links to Other Sites</h2> 101 | 102 | <p> 103 | Our Service may contain links to other sites. If you click on a third-party 104 | link, you will be directed to that site. Note that these external sites are 105 | not operated by us. Therefore, we strongly advise you to review the Privacy 106 | Policy of these websites. We have no control over, and assume no 107 | responsibility for the content, privacy policies, or practices of any 108 | third-party sites or services. 109 | </p> 110 | 111 | <p>Children’s Privacy</p> 112 | 113 | <p> 114 | Our Services do not address anyone under the age of 13. We do not knowingly 115 | collect personal identifiable information from children under 13. In the 116 | case we discover that a child under 13 has provided us with personal 117 | information, we immediately delete this from our servers. If you are a 118 | parent or guardian and you are aware that your child has provided us with 119 | personal information, please contact us so that we will be able to do 120 | necessary actions. 121 | </p> 122 | 123 | <h2>Changes to This Privacy Policy</h2> 124 | 125 | <p> 126 | We may update our Privacy Policy from time to time. Thus, we advise you to 127 | review this page periodically for any changes. We will notify you of any 128 | changes by posting the new Privacy Policy on this page. These changes are 129 | effective immediately, after they are posted on this page. 130 | </p> 131 | 132 | <h2>Contact Us</h2> 133 | 134 | <p> 135 | If you have any questions or suggestions about our Privacy Policy, do not 136 | hesitate to contact us. 137 | </p> 138 | -------------------------------------------------------------------------------- /contracts/oracle.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at BscScan.com on 2023-08-23 3 | */ 4 | 5 | /** 6 | *Submitted for verification at BscScan.com on 2023-01-17 7 | */ 8 | 9 | //SPDX-License-Identifier: Unlicense 10 | 11 | 12 | pragma solidity 0.8.19; 13 | 14 | contract owned { 15 | address payable public owner; 16 | 17 | constructor () { 18 | owner = payable(msg.sender); 19 | } 20 | 21 | modifier onlyOwner { 22 | require(msg.sender == owner,"only owner method"); 23 | _; 24 | } 25 | 26 | function transferOwnership(address payable newOwner) onlyOwner public { 27 | owner = newOwner; 28 | } 29 | } 30 | 31 | contract limited is owned { 32 | mapping (address => bool) canAsk; 33 | 34 | 35 | modifier onlyCanAsk { 36 | require(canAsk[msg.sender]); 37 | _; 38 | } 39 | 40 | 41 | 42 | function changeAsk (address a,bool allow) onlyOwner public { 43 | canAsk[a] = allow; 44 | } 45 | 46 | } 47 | 48 | interface ICampaign { 49 | 50 | function update(bytes32 idRequest,uint64 likes,uint64 shares,uint64 views) external returns (bool ok); 51 | function updateBounty(bytes32 idProm,uint256 nbAbos) external returns (bool ok); 52 | } 53 | 54 | interface IERC20 { 55 | function transfer(address _to, uint256 _value) external; 56 | } 57 | 58 | contract oracle is limited { 59 | 60 | struct oracleUnit { 61 | bool granted; 62 | address token; 63 | uint256 fee; 64 | } 65 | 66 | mapping (address => oracleUnit) oracleList; 67 | 68 | modifier onlyCanAnswer { 69 | require(oracleList[msg.sender].granted || msg.sender == owner,"sender not in whitelist"); 70 | _; 71 | } 72 | 73 | /** 74 | * @dev Modifier to prevent reentrancy attacks during function execution. 75 | * It sets a flag before the function body and resets it after execution. 76 | */ 77 | modifier noReentrancy() { 78 | // Ensure that reentrancy is not already in progress 79 | require(!_withdrawalInProgress, "Reentrant call"); 80 | 81 | _withdrawalInProgress = true; // Set the flag to prevent reentrancy 82 | _; // This underscores the location where the modified function's body will be placed. 83 | _withdrawalInProgress = false; // Reset the flag after the function completes 84 | } 85 | 86 | modifier validCampaignAddress(address campaignContract){ 87 | require(campaignContract != address(0), "Invalid campaign address"); 88 | _; 89 | } 90 | bool private _withdrawalInProgress; // Reentrancy guard 91 | 92 | function changeAnswer (address oracleAddress,bool allow,address token,uint256 fee) onlyOwner validCampaignAddress(oracleAddress) public { 93 | oracleList[oracleAddress] = oracleUnit(allow,token,fee); 94 | 95 | emit OracleInfoUpdated(oracleAddress, allow, token, fee); 96 | } 97 | 98 | event AskRequest(bytes32 indexed idRequest, uint8 typeSN, string idPost,string idUser); 99 | event AnswerRequest(bytes32 indexed idRequest, uint64 likes, uint64 shares, uint64 views); 100 | 101 | event AskRequestBounty( uint8 typeSN, string idPost,string idUser,bytes32 idProm); 102 | event AnswerRequestBounty(bytes32 indexed idProm,uint256 nbAbos); 103 | event OracleInfoUpdated(address indexed oracleAddress, bool allow, address token, uint256 fee); 104 | 105 | 106 | function ask (uint8 typeSN,string memory idPost,string memory idUser, bytes32 idRequest) public onlyCanAsk 107 | { 108 | emit AskRequest(idRequest, typeSN, idPost, idUser ); 109 | } 110 | 111 | function askBounty(uint8 typeSN,string memory idPost,string memory idUser, bytes32 idProm) public onlyCanAsk 112 | { 113 | emit AskRequestBounty( typeSN, idPost, idUser, idProm); 114 | } 115 | 116 | function answer(address campaignContract,bytes32 idRequest,uint64 likes,uint64 shares, uint64 views) public onlyOwner validCampaignAddress(campaignContract){ 117 | ICampaign campaign = ICampaign(campaignContract); 118 | campaign.update(idRequest,likes,shares,views); 119 | emit AnswerRequest(idRequest,likes,shares,views); 120 | } 121 | 122 | function answerBounty(address campaignContract,bytes32 idProm,uint256 nbAbos) public onlyOwner validCampaignAddress(campaignContract){ 123 | ICampaign campaign = ICampaign(campaignContract); 124 | campaign.updateBounty(idProm,nbAbos); 125 | emit AnswerRequestBounty(idProm,nbAbos); 126 | } 127 | 128 | 129 | function thirdPartyAnswer(address campaignContract,bytes32 idRequest,uint64 likes,uint64 shares, uint64 views) public onlyCanAnswer validCampaignAddress(campaignContract) { 130 | ICampaign campaign = ICampaign(campaignContract); 131 | campaign.update(idRequest,likes,shares,views); 132 | emit AnswerRequest(idRequest,likes,shares,views); 133 | 134 | 135 | IERC20 erc20 = IERC20(oracleList[msg.sender].token); 136 | erc20.transfer(msg.sender,oracleList[msg.sender].fee); 137 | } 138 | 139 | function withdraw() onlyOwner noReentrancy public { 140 | owner.transfer(address(this).balance); 141 | } 142 | 143 | function transferToken (address token,address to,uint256 val) public onlyOwner { 144 | IERC20 erc20 = IERC20(token); 145 | erc20.transfer(to,val); 146 | } 147 | 148 | } -------------------------------------------------------------------------------- /conf/ssl/fullchain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFOzCCBCOgAwIBAgISBBdHCXLMc8F8vrvzkqfPL5cEMA0GCSqGSIb3DQEBCwUA 3 | MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD 4 | EwJSMzAeFw0yMjAzMDIxMjA5NTVaFw0yMjA1MzExMjA5NTRaMCYxJDAiBgNVBAMT 5 | G2FwaS1wcmVwcm9kMi5zYXR0LXRva2VuLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD 6 | ggEPADCCAQoCggEBANeC/ZH4Afmpgl03vMlsB8C8j1bBIo923XX1v5dacZgCLR/E 7 | v8zAYJ8aSCR+buesg6raTRnjrhWrel1zBvo3i3U2ciXj15THKB4ZHceFYGKdzMcg 8 | G9p23HpmlXwIePxdn6i4cQF1Zr4aXgyNmdbgH6D9EutWqsEtRYqHJMRMM1k9M2gY 9 | +/CtmggG9LugouM7RdW0WETc1BKImCX89+BuObIwmQEk4/ksA/8J2NPWy1Mc5L0P 10 | rPe6WPrH1hd4UCw3IiJzgTcKDZsHCRufm6mjEV2lUdkYCDrhRfETXE29d9jsQHbd 11 | +A2hqZxN99QFUecw+CzDAvOR0ZK3bPqs3JqCVNMCAwEAAaOCAlUwggJRMA4GA1Ud 12 | DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T 13 | AQH/BAIwADAdBgNVHQ4EFgQUQEWmx8s0a/pNj4um25ntZaqpEnwwHwYDVR0jBBgw 14 | FoAUFC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUF 15 | BzABhhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9y 16 | My5pLmxlbmNyLm9yZy8wJgYDVR0RBB8wHYIbYXBpLXByZXByb2QyLnNhdHQtdG9r 17 | ZW4uY29tMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYI 18 | KwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIIBAwYKKwYBBAHW 19 | eQIEAgSB9ASB8QDvAHUAQcjKsd8iRkoQxqE6CUKHXk4xixsD6+tLx2jwkGKWBvYA 20 | AAF/SsBgXwAABAMARjBEAiAm7mzw7gwqmDp4H3rh1Yw3375thJ0Kx9y2JYqM8BXf 21 | twIgUOMFj6btNUPCPW17+vJNeqgkn25R3aTSxGGJni/LaKYAdgApeb7wnjk5IfBW 22 | c59jpXflvld9nGAK+PlNXSZcJV3HhAAAAX9KwGI+AAAEAwBHMEUCIQDOO0Qnhfes 23 | ApEKnhm4+BJQZ0qMWHm3ZoAbIM26FV7ohgIgbAM7/tVeZabR7JI1p04TErqg6uNS 24 | 0myRYs0DYLg29McwDQYJKoZIhvcNAQELBQADggEBAHmGgCnrl8L8Nrmti149fb33 25 | Itm7USX3m0nfv0EQ4r5THbjNS1+QwCO1gJkoHSg0855g1cO3sI09TGaeONpUPtpg 26 | 5ckVMlZlDYlTQU+wd7i+IGz2UpWHDfmvDBaJZ2a8obKWuI2KkLo9Pj84ajNWrfuD 27 | K2yg79PRxe+duVYnXVr8Fjrd2IF78tWOpq9QCV0SikIw4F9WW4xICM/YfzEutVrU 28 | +aETaENyQHMch263asTX0H/SmSBnMfn90pMohVc/ZCkTcww7mmeJXP6ME3DRNW/T 29 | 6AxwA2Qs8mFjDaxik48HCM2wFRgsmlWRh1k0L0I3fyTBaGVlcWDYqOnv1yGY9nk= 30 | -----END CERTIFICATE----- 31 | -----BEGIN CERTIFICATE----- 32 | MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw 33 | TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh 34 | cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw 35 | WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg 36 | RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK 37 | AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP 38 | R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx 39 | sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm 40 | NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg 41 | Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG 42 | /kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC 43 | AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB 44 | Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA 45 | FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw 46 | AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw 47 | Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB 48 | gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W 49 | PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl 50 | ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz 51 | CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm 52 | lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 53 | avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 54 | yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O 55 | yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids 56 | hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ 57 | HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv 58 | MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX 59 | nLRbwHOoq7hHwg== 60 | -----END CERTIFICATE----- 61 | -----BEGIN CERTIFICATE----- 62 | MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ 63 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 64 | DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow 65 | TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh 66 | cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB 67 | AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC 68 | ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL 69 | wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D 70 | LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK 71 | 4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 72 | bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y 73 | sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ 74 | Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 75 | FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc 76 | SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql 77 | PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND 78 | TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw 79 | SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 80 | c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx 81 | +tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB 82 | ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu 83 | b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E 84 | U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu 85 | MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC 86 | 5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW 87 | 9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG 88 | WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O 89 | he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC 90 | Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 91 | -----END CERTIFICATE----- 92 | -------------------------------------------------------------------------------- /public/emailtemplate/create-tron-wallet.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html lang="en"> 3 | <head> 4 | <meta name="viewport" content="width=device-width" /> 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6 | <title>Atayen 7 | 11 | 12 | 13 | 17 | 88 | 89 | 90 | 93 |
94 | 95 |
96 | 97 |
98 |

New features on your

99 |

SaTT wallet

100 |
101 | 102 |

103 | You now have the possibility to create your Tron wallet. 104 |

105 | 106 | Create 107 | 108 |

If you have any questions, please contact us.

109 |

The entire SaTT team thanks you!

110 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node_satt_api", 3 | "version": "2.2.2", 4 | "author": "Atayen, Inc", 5 | "license": "ISC", 6 | "description": "Satt NodeJS backend", 7 | "main": "app.js", 8 | "scripts": { 9 | "test": "mocha --reporter spec --timeout 2000000", 10 | "supervisor": "NODE_ENV=testnet supervisor ./bin/www", 11 | "su": "NODE_ENV=local supervisor ./bin/www", 12 | "sup": "NODE_ENV=mainnet supervisor ./bin/www", 13 | "prepare": "husky install", 14 | "newVersion": " node changepackage.js", 15 | "push": "git checkout developement && git pull && node changepackage.js develop && git add package.json && git commit -m NewVersionpackage && git push" 16 | }, 17 | "dependencies": { 18 | "@apollo/client": "^3.7.13", 19 | "@atayen-org/transfer": "^2.3.8", 20 | "ansi-regex": ">=5.0.1", 21 | "api": "^4.5.1", 22 | "apollo-cache-inmemory": "^1.6.6", 23 | "apollo-client": "^2.6.10", 24 | "apollo-link-http": "^1.5.17", 25 | "axios": "^0.27.2", 26 | "bcrypt": "^5.0.1", 27 | "big.js": "^6.0.3", 28 | "bip32": "^4.0.0", 29 | "bip38": "^2.0.3", 30 | "bip39": "^3.0.3", 31 | "bitcoinjs-lib": "^4.0.3", 32 | "bitcore-lib": "^8.25.47", 33 | "body-parser": "^1.18.3", 34 | "chai": "^4.3.6", 35 | "chai-as-promised": "^7.1.1", 36 | "child_process": "^1.0.2", 37 | "cluster": "^0.7.7", 38 | "coinselect": "^3.1.11", 39 | "connect": "^3.7.0", 40 | "content-disposition": "^0.5.4", 41 | "cookie-parser": "^1.4.3", 42 | "cookie-session": "^2.0.0", 43 | "country-list": "^2.2.0", 44 | "cross-fetch": "^3.1.4", 45 | "deps": "^1.0.0", 46 | "dot-object": "^2.1.4", 47 | "dotenv": "^11.0.0", 48 | "ejs": "^3.1.8", 49 | "elliptic": "^6.5.4", 50 | "ethereumjs-wallet": "^1.0.1", 51 | "ethers": "^5.7.0", 52 | "execSync": "^1.0.2", 53 | "expand-url": "^0.1.3", 54 | "express": "^4.18.2", 55 | "express-ejs-layouts": "^2.5.0", 56 | "express-mongo-sanitize": "^2.2.0", 57 | "express-rate-limit": "^6.7.0", 58 | "express-session": "^1.15.6", 59 | "fast-csv": "^4.3.6", 60 | "filereader": "^0.10.3", 61 | "from-exponential": "^1.1.1", 62 | "geoip-lite": "^1.4.2", 63 | "google-auth-library": "^7.6.2", 64 | "graphql": "^16.0.1", 65 | "gridfs-stream": "^1.1.1", 66 | "handlebars": "^4.7.7", 67 | "hasha": "^5.2.2", 68 | "hdkey": "^2.0.1", 69 | "helmet": "^6.1.5", 70 | "http-cache-semantics": "^4.1.1", 71 | "i18n": "^0.8.6", 72 | "i18n-2": "^0.7.3", 73 | "i18n-express": "^1.1.3", 74 | "intl": "^1.2.5", 75 | "ip": "^1.1.5", 76 | "ipfs-http-client": "^56.0.2", 77 | "joi": "^17.9.2", 78 | "jquery": "^3.6.4", 79 | "js-cookie": "^2.2.0", 80 | "jsdom": "^21.1.0", 81 | "json-schema": ">=0.4.0", 82 | "json2csv": "^5.0.6", 83 | "jsonwebtoken": "^9.0.0", 84 | "legacy": "^0.0.3", 85 | "memory-cache": "^0.2.0", 86 | "mocha": "^10.1.0", 87 | "moment": "^2.22.2", 88 | "mongo-sanitize": "^1.1.0", 89 | "mongodb": "^4.16.0", 90 | "mongoose": "^5.13.17", 91 | "mongoose-auto-increment": "^5.0.1", 92 | "morgan": "^1.10.0", 93 | "mpath": "^0.8.4", 94 | "multer": "^1.4.5-lts.1", 95 | "multer-gridfs-storage": "^4.2.0", 96 | "mysql": "^2.18.1", 97 | "needle": "^3.3.1", 98 | "net": "^1.0.2", 99 | "node-cmd": "^5.0.0", 100 | "node-cron": "^2.0.3", 101 | "node-schedule": "^1.3.0", 102 | "nodemailer": ">=6.9.2", 103 | "npm": "^8.19.4", 104 | "passport": "^0.6.0", 105 | "passport-facebook": "^3.0.0", 106 | "passport-google-oauth20": "^2.0.0", 107 | "passport-linkedin-oauth2": "^2.0.0", 108 | "passport-local": "^1.0.0", 109 | "passport-oauth2": "^1.6.1", 110 | "passport-telegram": "^1.0.0", 111 | "passport-telegram-official": "^1.1.0", 112 | "passport-tiktok-auth": "^1.0.3", 113 | "path": "^0.12.7", 114 | "peer": "^1.0.0", 115 | "puppeteer": "^14.4.0", 116 | "qrcode": "^1.5.0", 117 | "reactstrap": "^9.1.10", 118 | "request-promise": "^4.2.6", 119 | "rlp": "^2.1.0", 120 | "save": "^2.9.0", 121 | "sharp": "^0.32.6", 122 | "sinon-chai": "^3.7.0", 123 | "socket.io": "^4.4.1", 124 | "solc": "^0.5.0", 125 | "speakeasy": "^2.0.0", 126 | "supervisor": "^0.12.0", 127 | "swagger-jsdoc": "^5.0.1", 128 | "swagger-ui-dist": ">=4.18.3", 129 | "swagger-ui-express": "^4.3.0", 130 | "tar": "^6.1.14", 131 | "tronweb": "^4.2.0", 132 | "twitter": "^1.1.0", 133 | "twitter-api-v2": "^1.14.2", 134 | "twitter-lite": "^1.1.0", 135 | "underscore": ">=1.12.1", 136 | "uuid": "^8.3.2", 137 | "validator": ">=13.7.0", 138 | "web3": "^1.9.0", 139 | "web3-eth-abi": "^1.8.1", 140 | "web3-eth-contract": "^1.8.1", 141 | "wif": "^2.0.6", 142 | "winston": "^3.3.3", 143 | "ws": "^7.4.6", 144 | "xmlhttprequest-ssl": ">=1.6.2" 145 | }, 146 | "devDependencies": { 147 | "eslint": "^8.10.0", 148 | "eslint-plugin-react": "^7.29.3", 149 | "husky": "^7.0.4", 150 | "lint-staged": "^12.3.3", 151 | "nodemon": "^2.0.15", 152 | "prettier": "2.6.2" 153 | }, 154 | "lint-staged": { 155 | "*.{js,css,md}": "prettier --write" 156 | }, 157 | "directories": { 158 | "test": "test" 159 | }, 160 | "repository": { 161 | "type": "git", 162 | "url": "git+ssh://git@bitbucket.org/satt-wallet/node-satt.git" 163 | }, 164 | "keywords": [], 165 | "bugs": { 166 | "url": "https://bitbucket.org/satt-wallet/node-satt/issues" 167 | }, 168 | "homepage": "https://bitbucket.org/satt-wallet/node-satt#readme" 169 | } 170 | -------------------------------------------------------------------------------- /public/emailtemplate/email_validated_keystore_code.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Atayen 7 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 34 | 35 | 36 | 46 | 47 | 48 | 58 | 59 | 60 | 74 | 75 | 76 | 86 | 87 | 88 | 105 | 106 | 107 | 147 | 148 |
16 | logo 17 |
25 | Confirm the download of your keystore 33 |
37 | You have initiated a download request for your keystore from the following address : {{walletAddr}} 45 |
49 | Your validation code 57 |
61 | {{code}} 73 |
77 | This code will only be valid for 5 min 85 |
95 | If you are not the originator of this action,
102 | please contact support.
104 |
108 | 115 | 121 | 127 | 133 |
134 | Copyright © 2023 Atayen, Inc.
144 | All right reserved 145 |
146 |
149 | 150 | 151 | -------------------------------------------------------------------------------- /public/emailtemplate/email_validated_code.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Atayen 7 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 34 | 35 | 36 | 46 | 47 | 48 | 60 | 61 | 62 | 72 | 73 | 74 | 88 | 89 | 90 | 100 | 101 | 102 | 119 | 120 | 121 | 161 | 162 |
16 | logo 17 |
24 | Welcome ! 33 |
37 | Your registration is almost complete ! 45 |
49 | Protecting your wallet is our priority.
Please 56 | confirme your account by entering this code at the 57 | validation page.
59 |
63 | Your validation code : 71 |
75 | {{code}} 87 |
91 | This code will only be valid for 5 min 99 |
109 | If you are not the originator of this registration,
116 | please contact support.
118 |
122 | 129 | 135 | 141 | 147 |
148 | Copyright © 2023 Atayen, Inc.
158 | All right reserved 159 |
160 |
163 | 164 | 165 | -------------------------------------------------------------------------------- /web3/graph.js: -------------------------------------------------------------------------------- 1 | module.exports = async function (app) { 2 | const fetch = require('cross-fetch/polyfill').fetch 3 | const createHttpLink = require('apollo-link-http').createHttpLink 4 | 5 | const { ApolloClient } = require('apollo-client') 6 | const { InMemoryCache } = require('apollo-cache-inmemory') 7 | const gql = require('graphql-tag') 8 | const APIURLBEP20 = app.config.APIURLBEP20 9 | const APIURLERC20 = app.config.APIURLERC20 10 | 11 | var graph = {} 12 | 13 | const httpLinkBEP20 = createHttpLink({ 14 | uri: APIURLBEP20, 15 | fetch: fetch, 16 | }) 17 | 18 | const httpLinkERC20 = createHttpLink({ 19 | uri: APIURLERC20, 20 | fetch: fetch, 21 | }) 22 | 23 | const clientBep20 = new ApolloClient({ 24 | link: httpLinkBEP20, 25 | cache: new InMemoryCache(), 26 | }) 27 | 28 | const clientErc20 = new ApolloClient({ 29 | link: httpLinkERC20, 30 | cache: new InMemoryCache(), 31 | }) 32 | 33 | const queryCampaignBep20 = gql` 34 | { 35 | campaigns(first: 1000) { 36 | id 37 | ratios 38 | bounties 39 | startDate 40 | endDate 41 | advertiser 42 | currentAmount 43 | token 44 | network 45 | isActive 46 | } 47 | } 48 | ` 49 | 50 | graph.promsBep20 = async (nbr) => { 51 | return new Promise(async (resolve, reject) => { 52 | let skip = nbr * 1000 53 | clientBep20 54 | .query({ 55 | query: gql`{ 56 | proms(first : 1000,skip:${skip}) { 57 | id 58 | campaign { 59 | id, 60 | ratios, 61 | bounties, 62 | startDate, 63 | endDate, 64 | advertiser, 65 | token, 66 | network, 67 | initialAmount, 68 | currentAmount, 69 | isActive 70 | } 71 | influencer 72 | token 73 | totalAmount 74 | typeSN 75 | idPost 76 | idUser 77 | isPayed 78 | isAccepted 79 | } 80 | } 81 | `, 82 | }) 83 | .then((data) => { 84 | resolve(data.data.proms) 85 | }) 86 | .catch((err) => {}) 87 | }) 88 | } 89 | 90 | graph.campaignsBep20 = async () => { 91 | return new Promise(async (resolve, reject) => { 92 | clientBep20 93 | .query({ 94 | query: queryCampaignBep20, 95 | }) 96 | .then((data) => { 97 | resolve(data.data.campaigns) 98 | }) 99 | .catch((err) => {}) 100 | }) 101 | } 102 | 103 | graph.campaignsErc20 = async () => { 104 | return new Promise(async (resolve, reject) => { 105 | clientErc20 106 | .query({ 107 | query: queryCampaignBep20, 108 | }) 109 | .then((data) => { 110 | resolve(data.data.campaigns) 111 | }) 112 | .catch((err) => {}) 113 | }) 114 | } 115 | 116 | graph.promsErc20 = async (nbr) => { 117 | return new Promise(async (resolve, reject) => { 118 | let skip = nbr * 1000 119 | clientErc20 120 | .query({ 121 | query: gql`{ 122 | proms(first : 1000,skip:${skip}) { 123 | id 124 | campaign { 125 | id, 126 | ratios, 127 | bounties, 128 | startDate, 129 | endDate, 130 | advertiser, 131 | token, 132 | network, 133 | initialAmount, 134 | currentAmount, 135 | isActive 136 | } 137 | influencer 138 | token 139 | totalAmount 140 | typeSN 141 | idPost 142 | idUser 143 | isPayed 144 | isAccepted 145 | } 146 | }`, 147 | }) 148 | .then((data) => { 149 | resolve(data.data.proms) 150 | }) 151 | .catch((err) => {}) 152 | }) 153 | } 154 | 155 | graph.promBep20 = async (idProm) => { 156 | return new Promise(async (resolve, reject) => { 157 | let request = gql`{ 158 | proms(where:{id:"${idProm}"}) { 159 | totalAmount 160 | typeSN 161 | idPost 162 | idUser 163 | campaign{ 164 | id 165 | initialAmount 166 | currentAmount 167 | token 168 | } 169 | 170 | } 171 | } 172 | ` 173 | clientBep20 174 | .query({ 175 | query: request, 176 | }) 177 | .then((data) => { 178 | resolve(data.data.proms) 179 | }) 180 | .catch((err) => {}) 181 | }) 182 | } 183 | 184 | graph.promErc20 = async (idProm) => { 185 | return new Promise(async (resolve, reject) => { 186 | let request = gql`{ 187 | proms(where:{id:"${idProm}"}) { 188 | totalAmount 189 | typeSN 190 | idPost 191 | idUser 192 | campaign{ 193 | id 194 | initialAmount 195 | currentAmount 196 | token 197 | } 198 | 199 | } 200 | } 201 | ` 202 | clientErc20 203 | .query({ 204 | query: request, 205 | }) 206 | .then((data) => { 207 | resolve(data.data.proms) 208 | }) 209 | .catch((err) => {}) 210 | }) 211 | } 212 | 213 | graph.getPromDetails = async (idProm) => { 214 | return new Promise(async (resolve, reject) => { 215 | let promBep20 = await app.graph.promBep20(idProm) 216 | let promErc20 = await app.graph.promErc20(idProm) 217 | let prom = promBep20.concat(promErc20) 218 | resolve(prom[0]) 219 | }) 220 | } 221 | 222 | graph.allCampaigns = async () => { 223 | return new Promise(async (resolve, reject) => { 224 | let campaignBep20 = await app.graph.campaignsBep20() 225 | let campaignsErc20 = await app.graph.campaignsErc20() 226 | let allCampaigns = campaignBep20.concat(campaignsErc20) 227 | resolve(allCampaigns) 228 | }) 229 | } 230 | 231 | graph.allProms = async (nbr) => { 232 | return new Promise(async (resolve, reject) => { 233 | let promsBep20 = await app.graph.promsBep20(nbr) 234 | let promsErc20 = await app.graph.promsErc20(nbr) 235 | let allProms = promsBep20.concat(promsErc20) 236 | resolve(allProms) 237 | }) 238 | } 239 | 240 | app.graph = graph 241 | 242 | return app 243 | } 244 | -------------------------------------------------------------------------------- /middleware/profileValidator.middleware.js: -------------------------------------------------------------------------------- 1 | const Joi = require('joi'); 2 | 3 | 4 | /********** 5 | * 6 | * SCHEMA FOR JOI 7 | * 8 | * ********************** */ 9 | 10 | // VALIDATION TRANSACTION PASSWORD 11 | const validatePassword = () => Joi.string().min(8).required().custom((value) => { 12 | const RegUpperCase = RegExp('[A-Z]'); 13 | const RegLowerCase = RegExp('[a-z]'); 14 | const RegNumber = RegExp('[0-9]'); 15 | const RegSpecialChar = RegExp('[^A-Za-z0-9]'); 16 | if(RegUpperCase.test(value) && RegLowerCase.test(value) && RegNumber.test(value) && RegSpecialChar.test(value)) { 17 | return value; 18 | } else throw Error('password not match') 19 | }); 20 | 21 | 22 | // VALIDATION ADDRESS 23 | const validateAddress = (pattern) => Joi.string().required().pattern(new RegExp(pattern)); 24 | 25 | 26 | // VALIDATION EMAIL 27 | const validateEmail = () => Joi.string().email({ tlds: { allow: false } }).regex(/^[^@]+@[^@]+\.[^@]+$/).required() 28 | 29 | 30 | 31 | // SCHEMAS OBJECT 32 | const schemas = { 33 | checkFileSchema: Joi.object({ 34 | mimetype: Joi.string().custom((value) => { 35 | if (value && value.startsWith('image/')) { 36 | return value; 37 | } else { 38 | throw new Error('File mimetype must start with "image/"'); 39 | } 40 | }).required() 41 | }).unknown(true), 42 | 43 | UpdateInterstsSchema: Joi.object({ 44 | interests: Joi.array().items(Joi.string()).required(), 45 | }), 46 | 47 | idCheckSchema: Joi.object({ 48 | id: Joi.string().required() 49 | }), 50 | 51 | confrimChangeMailSchema: Joi.object({ 52 | code: Joi.number().required() 53 | }), 54 | 55 | supportSchema: Joi.object({ 56 | name: Joi.string().allow(''), 57 | email: validateEmail(), 58 | subject: Joi.string().allow(''), 59 | message: Joi.string().allow('') 60 | }), 61 | 62 | changeEmailSchema: Joi.object({ 63 | pass: validatePassword(), 64 | email: validateEmail(), 65 | }), 66 | 67 | requestMoneySchema: Joi.object({ 68 | cryptoCurrency: Joi.string().required(), 69 | from: validateEmail(), 70 | message: Joi.string().allow(''), 71 | name: Joi.string().allow(''), 72 | price: Joi.number().unsafe().required(), 73 | to: validateEmail(), 74 | wallet: validateAddress("^0x[a-fA-F0-9]{40}$|^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$|T[A-Za-z1-9]{33}$"), 75 | }), 76 | 77 | idUserCheckSchema: Joi.object({ 78 | idUser: Joi.string().required() 79 | }), 80 | 81 | updateProfileSchema: Joi.alternatives().try( 82 | Joi.object({ 83 | address: Joi.string().allow('').required(), 84 | birthday: Joi.string().allow('').required(), 85 | city: Joi.string().allow('').required(), 86 | country: Joi.string().allow('').required(), 87 | zipCode: Joi.string().allow(''), 88 | email: validateEmail(), 89 | firstName: Joi.string().allow('').required(), 90 | gender: Joi.string().allow('').required(), 91 | lastName: Joi.string().allow('').required(), 92 | locale: Joi.string().allow('').required(), 93 | phone: Joi.object({ 94 | number: Joi.string().required(), 95 | internationalNumber: Joi.string().required(), 96 | nationalNumber: Joi.string().required(), 97 | e164Number: Joi.string().required(), 98 | countryCode: Joi.string().length(2).required(), 99 | dialCode: Joi.string().required() 100 | }).allow(null).required() 101 | }), 102 | Joi.object({ 103 | hasBiometrics: Joi.boolean().required() 104 | }), 105 | Joi.object({ 106 | is2FA: Joi.boolean().required() 107 | }), 108 | Joi.object({ 109 | photoUpdated: Joi.boolean().required() 110 | }), 111 | Joi.object({ 112 | enabled: Joi.number().required(), 113 | new: Joi.boolean().required() 114 | }) 115 | ), 116 | 117 | 118 | 119 | 120 | deleteLinkedinChannelSchema: Joi.object({ 121 | linkedinId: Joi.string().required(), 122 | organization: Joi.string().required(), 123 | }), 124 | 125 | verifyLinkSchema: Joi.object({ 126 | typeSN: Joi.number().required(), 127 | idUser: Joi.string().required(), 128 | idPost: Joi.string().required() 129 | }), 130 | 131 | ShareByActivitySchema: Joi.object({ 132 | activity: Joi.string().required(), 133 | }), 134 | 135 | uploadFileLegalKycSchema: Joi.object({ 136 | mimetype: Joi.string().custom((value) => { 137 | if (value && (value.startsWith('image/') || value === 'application/pdf')) { 138 | return value; 139 | } else { 140 | throw new Error('File mimetype must start with "image/"'); 141 | } 142 | }).required() 143 | }).unknown(true), 144 | 145 | addUserLegalProfileSchema: Joi.object({ 146 | type: Joi.string().required(), 147 | typeProof: Joi.string().allow('').required() 148 | }), 149 | idThreadsAccount: Joi.object({ 150 | id: Joi.string().required(), 151 | }) 152 | 153 | 154 | } 155 | 156 | 157 | 158 | 159 | 160 | /********** 161 | * 162 | * MIDDLEWARE VALIDATION 163 | * 164 | * ********************** */ 165 | 166 | 167 | // MIDDLEWARE FUNCTION 168 | const validationMiddleware = (schema, property) => (req, res, next) => { 169 | const {error} = schema.validate(req[property]); 170 | if(error) throw Error(error); 171 | else next(); 172 | } 173 | 174 | 175 | // CUSTOM MIDDLEWARE FOR SEND TOKEN USING BODY AND QUERY 176 | const validationCustomMiddleware = (schema1, property1, schema2, property2) => (req, res, next) => { 177 | const {error} = schema1.validate(req[property1]); 178 | if(error) { 179 | throw Error(error) 180 | } else { 181 | const {error} = schema2.validate(req[property2]); 182 | if(error) throw Error(error); 183 | else next(); 184 | } 185 | } 186 | 187 | 188 | 189 | 190 | 191 | module.exports = { 192 | addProfilePictureValidation: validationMiddleware(schemas.checkFileSchema, 'file'), 193 | UpdateInterstsValidation: validationMiddleware(schemas.UpdateInterstsSchema, 'body'), 194 | idCheckValidation: validationMiddleware(schemas.idCheckSchema, 'params'), 195 | confrimChangeMailValidation: validationMiddleware(schemas.confrimChangeMailSchema, 'body'), 196 | supportValidation: validationMiddleware(schemas.supportSchema, 'body'), 197 | changeEmailValidation: validationMiddleware(schemas.changeEmailSchema, 'body'), 198 | requestMoneyValidation: validationMiddleware(schemas.requestMoneySchema, 'body'), 199 | idUserCheckValidation: validationMiddleware(schemas.idUserCheckSchema, 'params'), 200 | updateProfileValidation: validationMiddleware(schemas.updateProfileSchema, 'body'), 201 | deleteLinkedinChannelValidation: validationMiddleware(schemas.deleteLinkedinChannelSchema, 'params'), 202 | verifyLinkValidation: validationMiddleware(schemas.verifyLinkSchema, 'params'), 203 | ShareByActivityValidation: validationMiddleware(schemas.ShareByActivitySchema, 'params'), 204 | addUserLegalProfileValidation: validationCustomMiddleware(schemas.uploadFileLegalKycSchema, 'file', schemas.addUserLegalProfileSchema, 'body'), 205 | idThreadsAccountValidation: validationMiddleware(schemas.idThreadsAccount, 'params') 206 | }; -------------------------------------------------------------------------------- /model/twitterProfile.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const twitterProfileSchema = mongoose.Schema( 4 | { 5 | id: { type: String }, 6 | username: { type: String }, 7 | displayName: { type: String }, 8 | photos: [ 9 | { 10 | value: { type: String }, 11 | }, 12 | ], 13 | provider: { type: String }, 14 | _raw: { type: String }, 15 | _json: { 16 | id: { type: String }, 17 | id_str: { type: String }, 18 | name: { type: String }, 19 | screen_name: { type: String }, 20 | location: { type: String }, 21 | description: { type: String }, 22 | url: { type: String }, 23 | entities: { 24 | description: { 25 | urls: [], 26 | }, 27 | }, 28 | protected: { type: Boolean }, 29 | followers_count: { type: Number }, 30 | friends_count: { type: Number }, 31 | listed_count: { type: Number }, 32 | created_at: { type: String }, 33 | favourites_count: { type: Number }, 34 | utc_offset: { type: String }, 35 | time_zone: { type: String }, 36 | geo_enabled: { type: Boolean }, 37 | verified: { type: Boolean }, 38 | statuses_count: { type: Number }, 39 | lang: { type: String }, 40 | status: { 41 | created_at: { type: String }, 42 | id: { type: String }, 43 | id_str: { type: String }, 44 | text: { type: String }, 45 | truncated: { type: Boolean }, 46 | entities: { 47 | hashtags: [ 48 | { 49 | text: { type: String }, 50 | indices: [{ type: Number }], 51 | }, 52 | ], 53 | symbols: [], 54 | user_mentions: [ 55 | { 56 | screen_name: { type: String }, 57 | name: { type: String }, 58 | id: { type: String }, 59 | id_str: { type: String }, 60 | indices: [{ type: Number }], 61 | }, 62 | ], 63 | urls: [ 64 | { 65 | url: { type: String }, 66 | expanded_url: { type: String }, 67 | display_url: { type: String }, 68 | indices: [{ type: Number }], 69 | }, 70 | ], 71 | }, 72 | source: { type: String }, 73 | in_reply_to_status_id: { type: String }, 74 | in_reply_to_status_id_str: { type: String }, 75 | in_reply_to_user_id: { type: String }, 76 | in_reply_to_user_id_str: { type: String }, 77 | in_reply_to_screen_name: { type: String }, 78 | geo: { type: String }, 79 | coordinates: { type: String }, 80 | place: { type: String }, 81 | contributors: { type: String }, 82 | retweeted_status: { 83 | created_at: { type: String }, 84 | id: { type: String }, 85 | id_str: { type: String }, 86 | text: { type: String }, 87 | truncated: { type: Boolean }, 88 | entities: { 89 | hashtags: [ 90 | { 91 | text: { type: String }, 92 | indices: [{ type: Number }], 93 | }, 94 | ], 95 | symbols: [], 96 | user_mentions: [], 97 | urls: [ 98 | { 99 | url: { type: String }, 100 | expanded_url: { type: String }, 101 | display_url: { type: String }, 102 | indices: [{ type: Number }], 103 | }, 104 | ], 105 | }, 106 | source: { type: String }, 107 | in_reply_to_status_id: { type: String }, 108 | in_reply_to_status_id_str: { type: String }, 109 | in_reply_to_user_id: { type: String }, 110 | in_reply_to_user_id_str: { type: String }, 111 | in_reply_to_screen_name: { type: String }, 112 | geo: { type: String }, 113 | coordinates: { type: String }, 114 | place: { type: String }, 115 | contributors: { type: String }, 116 | is_quote_status: { type: Boolean }, 117 | retweet_count: { type: Number }, 118 | favorite_count: { type: Number }, 119 | favorited: { type: Boolean }, 120 | retweeted: { type: Boolean }, 121 | possibly_sensitive: { type: Boolean }, 122 | lang: { type: String }, 123 | }, 124 | is_quote_status: { type: Boolean }, 125 | retweet_count: { type: Number }, 126 | favorite_count: { type: Number }, 127 | favorited: { type: Boolean }, 128 | retweeted: { type: Boolean }, 129 | possibly_sensitive: { type: Boolean }, 130 | lang: { type: String }, 131 | }, 132 | contributors_enabled: { type: Boolean }, 133 | is_translator: { type: Boolean }, 134 | is_translation_enabled: { type: Boolean }, 135 | profile_background_color: { type: String }, 136 | profile_background_image_url: { type: String }, 137 | profile_background_image_url_https: { type: String }, 138 | profile_background_tile: { type: Boolean }, 139 | profile_image_url: { type: String }, 140 | profile_image_url_https: { type: String }, 141 | profile_banner_url: { type: String }, 142 | profile_link_color: { type: String }, 143 | profile_sidebar_border_color: { type: String }, 144 | profile_sidebar_fill_color: { type: String }, 145 | profile_text_color: { type: String }, 146 | profile_use_background_image: { type: Boolean }, 147 | has_extended_profile: { type: Boolean }, 148 | default_profile: { type: Boolean }, 149 | default_profile_image: { type: Boolean }, 150 | following: { type: Boolean }, 151 | follow_request_sent: { type: Boolean }, 152 | notifications: { type: Boolean }, 153 | translator_type: { type: String }, 154 | withheld_in_countries: [], 155 | suspended: { type: Boolean }, 156 | needs_phone_verification: { type: Boolean }, 157 | }, 158 | _accessLevel: { type: String }, 159 | access_token_key: { type: String }, 160 | access_token_secret: { type: String }, 161 | UserId: { type: Number, required: true, ref: 'user' }, 162 | subscibers: { type: Number }, 163 | twitter_id: { type: String }, 164 | }, 165 | { 166 | collection: 'twitter_profile', 167 | } 168 | ) 169 | 170 | const TwitterProfile = mongoose.model('twitter_profile', twitterProfileSchema) 171 | module.exports = TwitterProfile 172 | -------------------------------------------------------------------------------- /public/emailtemplate/contact_support.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Atayen 10 | 14 | 15 | 19 | 213 | 214 | 215 |
216 |
217 |
218 |
219 | 223 |
224 |
225 |
226 |

Un nouvel Email a été envoyé au support

227 |
228 |
229 |
230 | From: <%= letter.from %> 231 |
232 |
233 |
234 | subject : <%= letter.subject %> 235 |
236 |
237 |
Message : <%= letter.message %>
238 |
239 | 243 |
244 | 245 | 246 | -------------------------------------------------------------------------------- /public/emailtemplate/Email_Template_link_added.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Atayen 11 | 15 | 16 | 20 | 202 | 203 | 204 |
205 |
206 |
207 |
208 | 213 |
214 |
215 |
216 | 220 |

{{__ "link_added"}}

221 |

222 | {{__ "new_link"}} {{cmp_link}} to {{cmp_name}} {{__ 223 | "new_link_campaign"}} 224 |

225 |
226 |
227 |

{{__ "insert-question"}}

228 |
{{__ "valid_wish"}}
229 |
230 | 238 |
239 | 240 | 241 | --------------------------------------------------------------------------------