order sharing
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
DEXORDER_PORT=3001
|
DEXORDER_PORT=3001
|
||||||
DEXORDER_CORS=http://localhost:3000
|
DEXORDER_APP_URL=http://localhost:3000
|
||||||
|
|
||||||
DEXORDER_DB_URL=postgresql://dexorder:redroxed@localhost:5432/dexorder
|
DEXORDER_DB_URL=postgresql://dexorder:redroxed@localhost:5432/dexorder
|
||||||
DEXORDER_REDIS_URL=redis://localhost:6379
|
DEXORDER_REDIS_URL=redis://localhost:6379
|
||||||
@@ -19,3 +19,9 @@ DEXORDER_RPC_URL_1337=http://localhost:8545
|
|||||||
# use this in the URL to bypass IP country check for development / debug
|
# use this in the URL to bypass IP country check for development / debug
|
||||||
# http://localhost:3000/...?approval=...
|
# http://localhost:3000/...?approval=...
|
||||||
DEXORDER_REGION_APPROVAL=6ehWWH98diqv39gWZcPo
|
DEXORDER_REGION_APPROVAL=6ehWWH98diqv39gWZcPo
|
||||||
|
|
||||||
|
DEXORDER_SNAPSHOT_S3_BUCKET_NAME=snapshot
|
||||||
|
DEXORDER_SNAPSHOT_S3_ACCESS_KEY_ID=5c73e3059596e6726d22e7aa5d2d23d6
|
||||||
|
DEXORDER_SNAPSHOT_S3_SECRET_ACCESS_KEY=a543189cea7d87c891e5abef7fabd7c1759b5063a667b3f29217a6a496a7342a
|
||||||
|
DEXORDER_SNAPSHOT_S3_ENDPOINT=https://3d7004962a10203cb8fecacc6a8ff502.r2.cloudflarestorage.com
|
||||||
|
DEXORDER_SNAPSHOT_BASE_URL=https://3d7004962a10203cb8fecacc6a8ff502.r2.cloudflarestorage.com/snapshot
|
||||||
|
|||||||
35
io.js
35
io.js
@@ -2,13 +2,38 @@ import {createServer} from "http";
|
|||||||
import {Server} from "socket.io";
|
import {Server} from "socket.io";
|
||||||
import { createAdapter } from "@socket.io/redis-adapter";
|
import { createAdapter } from "@socket.io/redis-adapter";
|
||||||
import {redis} from "./cache.js";
|
import {redis} from "./cache.js";
|
||||||
|
import {fileURLToPath} from "url";
|
||||||
|
import path from "path";
|
||||||
|
import express from "express";
|
||||||
|
import {engine} from "express-handlebars";
|
||||||
|
import {initSnapShare} from "./snapshare.js";
|
||||||
|
import cors from "cors";
|
||||||
|
|
||||||
const options = {
|
const socketIoOptions = {
|
||||||
}
|
}
|
||||||
if( process.env.DEXORDER_CORS )
|
if( process.env.DEXORDER_APP_URL )
|
||||||
options['cors'] = {origin:process.env.DEXORDER_CORS}
|
socketIoOptions['cors'] = {origin:process.env.DEXORDER_APP_URL}
|
||||||
export const httpServer = createServer()
|
|
||||||
export const io = new Server(httpServer, options)
|
// Setup Express
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.engine('handlebars', engine({
|
||||||
|
defaultLayout: false,
|
||||||
|
}
|
||||||
|
));
|
||||||
|
app.set('view engine', 'handlebars');
|
||||||
|
app.set('views', path.join(__dirname, 'views')); // Set the views directory
|
||||||
|
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
app.use(cors())
|
||||||
|
|
||||||
|
initSnapShare(app)
|
||||||
|
|
||||||
|
export const httpServer = createServer(app)
|
||||||
|
export const io = new Server(httpServer, socketIoOptions)
|
||||||
const pubClient = redis.duplicate();
|
const pubClient = redis.duplicate();
|
||||||
await pubClient.connect()
|
await pubClient.connect()
|
||||||
const adapter = createAdapter(pubClient, redis, {/*key:'socket.io'*/})
|
const adapter = createAdapter(pubClient, redis, {/*key:'socket.io'*/})
|
||||||
|
|||||||
@@ -11,11 +11,17 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "unlicensed",
|
"license": "unlicensed",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-s3": "^3.787.0",
|
||||||
"@isaacs/ttlcache": "^1.4.1",
|
"@isaacs/ttlcache": "^1.4.1",
|
||||||
"@maxmind/geoip2-node": "^5.0.0",
|
"@maxmind/geoip2-node": "^5.0.0",
|
||||||
"@socket.io/redis-adapter": "^8.2.1",
|
"@socket.io/redis-adapter": "^8.2.1",
|
||||||
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"ethers": "^6.7.1",
|
"ethers": "^6.7.1",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"express-handlebars": "^8.0.2",
|
||||||
|
"multer": "^1.4.5-lts.2",
|
||||||
|
"multer-s3": "^3.0.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"redis": "^4.6.10",
|
"redis": "^4.6.10",
|
||||||
"socket.io": "^4.7.2",
|
"socket.io": "^4.7.2",
|
||||||
|
|||||||
61
snapshare.js
Normal file
61
snapshare.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import {PutObjectCommand, S3Client} from "@aws-sdk/client-s3";
|
||||||
|
import cors from 'cors'
|
||||||
|
import {urlencoded} from "express";
|
||||||
|
import crypto from "crypto";
|
||||||
|
|
||||||
|
const SNAPSHOT_URL = process.env.DEXORDER_SNAPSHOT_URL;
|
||||||
|
const APP_URL = process.env.DEXORDER_APP_URL;
|
||||||
|
|
||||||
|
const S3_BUCKET = process.env.DEXORDER_SNAPSHOT_S3_BUCKET_NAME;
|
||||||
|
const S3_ACCESS_KEY_ID = process.env.DEXORDER_SNAPSHOT_S3_ACCESS_KEY_ID;
|
||||||
|
const S3_SECRET_ACCESS_KEY = process.env.DEXORDER_SNAPSHOT_S3_SECRET_ACCESS_KEY;
|
||||||
|
const S3_ENDPOINT = process.env.DEXORDER_SNAPSHOT_S3_ENDPOINT; // e.g., 'https://<ACCOUNT_ID>.r2.cloudflarestorage.com/'
|
||||||
|
|
||||||
|
const s3 = new S3Client({
|
||||||
|
region: "auto",
|
||||||
|
endpoint: S3_ENDPOINT,
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: S3_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: S3_SECRET_ACCESS_KEY,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export function initSnapShare(app) {
|
||||||
|
// this URL is called by the frontend to upload a snapshot image for use on a share page
|
||||||
|
app.put('/snapshot', cors({origin: process.env.DEXORDER_APP_URL}),
|
||||||
|
(req, res) => {
|
||||||
|
const chunks = [];
|
||||||
|
req.on('data', chunk => chunks.push(chunk))
|
||||||
|
req.on('error', (err) => res.status(500).send('Error reading body'))
|
||||||
|
req.on('end', () => {
|
||||||
|
const filename = crypto.randomUUID() + '.png';
|
||||||
|
const body = Buffer.concat(chunks);
|
||||||
|
s3.send(new PutObjectCommand({
|
||||||
|
Bucket: S3_BUCKET,
|
||||||
|
Key: filename,
|
||||||
|
Body: body,
|
||||||
|
ContentType: 'image/png',
|
||||||
|
ACL: 'public-read', // or private, depending on your needs
|
||||||
|
})).then(sent => {
|
||||||
|
res.send(filename)
|
||||||
|
}).catch(err => {
|
||||||
|
console.log('upload error', err)
|
||||||
|
res.status(500).send('error')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// this link returns a "share page" that shows the snapshot of the trade setup then redirects
|
||||||
|
// to the order page with the trade data loaded from the URL
|
||||||
|
app.get('/share', (req, res) => {
|
||||||
|
console.log('request', req)
|
||||||
|
const imageFilename = req.query.i; // c = snapshot code
|
||||||
|
const data = {
|
||||||
|
imageUrl: SNAPSHOT_URL + '/' + imageFilename,
|
||||||
|
redirectUrl: APP_URL + '/share?d=' + urlencoded(req.query.d), // d=data
|
||||||
|
};
|
||||||
|
res.render('share', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
19
views/share.handlebars
Normal file
19
views/share.handlebars
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<html lang="en/US">
|
||||||
|
<head>
|
||||||
|
<title>Dexorder Trade Setup</title>
|
||||||
|
<meta property="og:title" content="Dexorder Trade Setup">
|
||||||
|
<meta property="og:description" content="Trade this setup on Dexorder">
|
||||||
|
<meta property="og:image" content="{{{imageUrl}}}">
|
||||||
|
<meta property="og:url" content="https://app.dexorder.trade/">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="Dexorder Trade Setup">
|
||||||
|
<meta name="twitter:description" content="Trade this setup on Dexorder">
|
||||||
|
<meta name="twitter:image" content="{{{imageUrl}}}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="{{imageUrl}}" alt="Chart" width="100%"/>
|
||||||
|
<script language="javascript">window.location='{{{redirectUrl}}}'</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user