order sharing

This commit is contained in:
tim
2025-04-22 16:15:14 -04:00
parent 0b29539e0a
commit ff0d71054b
6 changed files with 1973 additions and 10 deletions

View File

@@ -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
View File

@@ -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'*/})

View File

@@ -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
View 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
View 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>

1854
yarn.lock

File diff suppressed because it is too large Load Diff