Skip to content

Commit

Permalink
Merge pull request #342 from pendulum-chain/staging-conflict-fixes
Browse files Browse the repository at this point in the history
Create release.
  • Loading branch information
gianfra-t authored Dec 23, 2024
2 parents 9a2b397 + d7fc7df commit 8aa829d
Show file tree
Hide file tree
Showing 148 changed files with 4,091 additions and 3,883 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/autodeploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ run-name: Gitlab Pipeline Executor
on:
push:
branches:
- polygon-prototype
- polygon-prototype-staging
jobs:
Execute-Gitlab-Pipeline:
runs-on: ubuntu-latest
Expand All @@ -13,4 +13,4 @@ jobs:
- name: Triggers Gitlab Pipeline
run: |
ls ${{ github.workspace }}
curl -X POST -F token=${{ secrets.GITLAB_TRIGGER }} -F "ref=development" -F "variables[PRODUCTION]=N" -F "variables[STAGING]=N" -F "variables[PRODPOL]=Y" -F "variables[STAGPOL]=N" https://gitlab.com/api/v4/projects/${{ secrets.PROJECT_ID }}/trigger/pipeline
curl -X POST -F token=${{ secrets.GITLAB_TRIGGER }} -F "ref=development" -F "variables[PRODUCTION]=N" -F "variables[STAGING]=N" -F "variables[PRODPOL]=N" -F "variables[STAGPOL]=Y" https://gitlab.com/api/v4/projects/${{ secrets.PROJECT_ID }}/trigger/pipeline
9 changes: 8 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ package-lock.json
package.json
yarn.lock
favicon.png
.prettierignore
.prettierignore

CHANGELOG.md
**/*.svg
.prettierignore
.gitignore
*.png
*.svg
*.webp
*.jpg
*.jpeg
*.gif
_redirects
LICENSE
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Vortex

[![Netlify Status](https://api.netlify.com/api/v1/badges/aa69406a-f4a1-4693-aed0-8478f1d1fabd/deploy-status)](https://app.netlify.com/sites/pendulum-portal-alpha/deploys)
  ![TypeScript](https://img.shields.io/badge/-TypeSript-05122A?style=flat&logo=typescript) 
[![Netlify Status](https://api.netlify.com/api/v1/badges/27783b79-512d-4205-89c1-d3ead6e3ed46/deploy-status)](https://app.netlify.com/sites/pendulum-pay/deploys) 
![TypeScript](https://img.shields.io/badge/-TypeSript-05122A?style=flat&logo=typescript) 
![Preact](https://img.shields.io/badge/-Preact-05122A?style=flat&logo=preact) 
![Vite](https://img.shields.io/badge/-Vite-05122A?style=flat&logo=vite) 
![Polkadot](https://img.shields.io/badge/-Polkadot-05122A?style=flat&logo=polkadot) 
![Ethereum](https://img.shields.io/badge/-Ethereum-05122A?style=flat&logo=ethereum) 

---

Expand Down
13 changes: 5 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"packageManager": "yarn@4.5.0+sha512.837566d24eec14ec0f5f1411adb544e892b3454255e61fdef8fd05f3429480102806bac7446bc9daff3896b01ae4b62d00096c7e989f1596f2af10b927532f39",
"scripts": {
"dev": "vite --host",
"build": "tsc && vite build && cp -R src/assets/coins dist/assets/coins && cp _redirects dist/_redirects",
"build": "tsc && NODE_OPTIONS='--max_old_space_size=8192' vite build && cp -R src/assets/coins dist/assets/coins && cp _redirects dist/_redirects",
"preview": "vite preview",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix",
Expand Down Expand Up @@ -38,17 +38,15 @@
"@reown/appkit-adapter-wagmi": "^1.3.1",
"@sentry/react": "^8.36.0",
"@sentry/vite-plugin": "^2.22.6",
"@talismn/connect-components": "^1.1.8",
"@talismn/connect-wallets": "^1.2.5",
"@tanstack/react-query": "^5.45.1",
"@talismn/connect-components": "^1.1.9",
"@tanstack/react-query": "^5.61.0",
"@walletconnect/modal": "^2.6.2",
"@walletconnect/universal-provider": "^2.12.2",
"autoprefixer": "^10.4.19",
"big.js": "^6.2.1",
"bn.js": "^5.2.1",
"buffer": "^6.0.3",
"daisyui": "^4.11.1",
"ethers": "^6.13.4",
"framer-motion": "^11.2.14",
"postcss": "^8.4.38",
"preact": "^10.12.1",
Expand All @@ -57,8 +55,7 @@
"react-dom": "npm:@preact/compat@18.3.1",
"react-hook-form": "^7.51.5",
"react-router-dom": "^6.8.1",
"react-toastify": "^10.0.5",
"siwe": "^2.3.2",
"react-toastify": "^10.0.6",
"stellar-base": "^11.0.1",
"stellar-sdk": "^11.3.0",
"tailwind": "^4.0.0",
Expand All @@ -81,7 +78,7 @@
"@preact/preset-vite": "^2.9.1",
"@types/big.js": "^6",
"@types/bn.js": "^5",
"@types/node": "^18.14.1",
"@types/node": "^22.7.5",
"@types/react": "^18.3.10",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ require('dotenv').config();
const { spreadsheet } = require('../../config/vars');
const { initGoogleSpreadsheet, getOrCreateSheet, appendData } = require('../services/spreadsheet.service');

exports.storeDataInGoogleSpreadsheet = async (req, res, spreadsheetId, sheetHeaderValues) => {
async function storeDataInGoogleSpreadsheet(req, res, spreadsheetId, sheetHeaderValues) {
try {
// We expect the data to be an object that matches our schema
const data = req.body;
Expand All @@ -12,7 +12,6 @@ exports.storeDataInGoogleSpreadsheet = async (req, res, spreadsheetId, sheetHead
const sheet = await initGoogleSpreadsheet(spreadsheetId, spreadsheet.googleCredentials).then((doc) =>
getOrCreateSheet(doc, sheetHeaderValues),
);

if (sheet) {
console.log('Appending data to sheet');
await appendData(sheet, data);
Expand All @@ -24,4 +23,6 @@ exports.storeDataInGoogleSpreadsheet = async (req, res, spreadsheetId, sheetHead
console.error('Error in storeData:', error);
return res.status(500).json({ error: 'Failed to store data', details: error.message });
}
};
}

module.exports = { storeDataInGoogleSpreadsheet };
4 changes: 2 additions & 2 deletions signer-service/src/api/controllers/siwe.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ exports.sendSiweMessage = async (req, res) => {
exports.validateSiweSignature = async (req, res) => {
const { nonce, signature, siweMessage } = req.body;
try {
await verifyAndStoreSiweMessage(nonce, signature, siweMessage);
const address = await verifyAndStoreSiweMessage(nonce, signature, siweMessage);

const token = {
nonce,
signature,
};

res.cookie('authToken', token, {
res.cookie(`authToken_${address}`, token, {
httpOnly: true,
secure: true,
sameSite: 'Strict',
Expand Down
26 changes: 3 additions & 23 deletions signer-service/src/api/controllers/stellar.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ exports.createStellarTransaction = async (req, res, next) => {
req.body.accountId,
req.body.maxTime,
req.body.assetCode,
req.body.baseFee,
);
return res.json({ signature, sequence, public: FUNDING_PUBLIC_KEY });
} catch (error) {
Expand All @@ -44,6 +45,7 @@ exports.changeOpTransaction = async (req, res, next) => {
req.body.paymentData,
req.body.maxTime,
req.body.assetCode,
req.body.baseFee,
);
return res.json({ signature, public: FUNDING_PUBLIC_KEY });
} catch (error) {
Expand All @@ -54,36 +56,14 @@ exports.changeOpTransaction = async (req, res, next) => {

exports.signSep10Challenge = async (req, res, next) => {
try {
let maybeChallengeSignature;
let maybeNonce;
if (req.cookies?.authToken) {
maybeChallengeSignature = req.cookies.authToken.signature;
maybeNonce = req.cookies.authToken.nonce;
}

if (Boolean(req.body.memo) && (!maybeChallengeSignature || !maybeNonce)) {
return res.status(401).json({
error: 'Missing signature or nonce',
});
}

let { masterClientSignature, masterClientPublic, clientSignature, clientPublic } = await signSep10Challenge(
req.body.challengeXDR,
req.body.outToken,
req.body.clientPublicKey,
maybeChallengeSignature,
maybeNonce,
req.derivedMemo, // Derived in middleware
);
return res.json({ masterClientSignature, masterClientPublic, clientSignature, clientPublic });
} catch (error) {
if (error.message.includes('Could not verify signature')) {
// Distinguish between failed signature check and other errors.
return res.status(401).json({
error: 'Signature validation failed.',
details: error.message,
});
}

console.error('Error in signSep10Challenge:', error);
return res.status(500).json({ error: 'Failed to sign challenge', details: error.message });
}
Expand Down
36 changes: 29 additions & 7 deletions signer-service/src/api/controllers/storage.controller.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const { spreadsheet } = require('../../config/vars');
const { storeDataInGoogleSpreadsheet } = require('./googleSpreadSheet.controller');
const { storeDataInGoogleSpreadsheet } = require('./googleSpreadSheet.controller.js');

// These are the headers for the Google Spreadsheet
const DUMP_SHEET_HEADER_VALUES = [
// These are the headers for the Google Spreadsheet for polygon offramp
const DUMP_SHEET_HEADER_VALUES_EVM = [
'timestamp',
'polygonAddress',
'offramperAddress',
'stellarEphemeralPublicKey',
'pendulumEphemeralPublicKey',
'nablaApprovalTx',
Expand All @@ -20,7 +20,29 @@ const DUMP_SHEET_HEADER_VALUES = [
'squidRouterReceiverHash',
];

exports.DUMP_SHEET_HEADER_VALUES = DUMP_SHEET_HEADER_VALUES;
const DUMP_SHEET_HEADER_VALUES_ASSETHUB = [
'timestamp',
'offramperAddress',
'stellarEphemeralPublicKey',
'pendulumEphemeralPublicKey',
'nablaApprovalTx',
'nablaSwapTx',
'spacewalkRedeemTx',
'stellarOfframpTx',
'stellarCleanupTx',
'inputAmount',
'inputTokenType',
'outputAmount',
'outputTokenType',
];
exports.DUMP_SHEET_HEADER_VALUES_ASSETHUB = DUMP_SHEET_HEADER_VALUES_ASSETHUB;
exports.DUMP_SHEET_HEADER_VALUES_EVM = DUMP_SHEET_HEADER_VALUES_EVM;

exports.storeData = async (req, res) => {
const sheetHeaderValues = req.body.offramperAddress.includes('0x')
? DUMP_SHEET_HEADER_VALUES_EVM
: DUMP_SHEET_HEADER_VALUES_ASSETHUB;
console.log(sheetHeaderValues);

exports.storeData = async (req, res) =>
storeDataInGoogleSpreadsheet(req, res, spreadsheet.storageSheetId, DUMP_SHEET_HEADER_VALUES);
storeDataInGoogleSpreadsheet(req, res, spreadsheet.storageSheetId, sheetHeaderValues);
};
9 changes: 3 additions & 6 deletions signer-service/src/api/controllers/subsidize.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ const { PENDULUM_WSS, PENDULUM_FUNDING_SEED } = require('../../constants/constan

const { TOKEN_CONFIG, getPaddedAssetCode } = require('../../constants/tokenConfig');

const TOKEN_TO_SWAP = 'usdc.axl';

exports.subsidizePreSwap = async (req, res) => {
try {
const { pendulumCurrencyId, maximumSubsidyAmountRaw } = TOKEN_CONFIG[TOKEN_TO_SWAP];
const { address, amountRaw, tokenToSubsidize } = req.body;
console.log('Subsidize pre swap', address, amountRaw, tokenToSubsidize);

const { address, amountRaw } = req.body;
console.log('Subsidize pre swap', address, amountRaw);
const { pendulumCurrencyId, maximumSubsidyAmountRaw } = TOKEN_CONFIG[tokenToSubsidize.toLowerCase()];

if (Big(amountRaw).gt(Big(maximumSubsidyAmountRaw))) {
throw new Error('Amount exceeds maximum subsidy amount');
Expand All @@ -25,7 +23,6 @@ exports.subsidizePreSwap = async (req, res) => {
const wsProvider = new WsProvider(PENDULUM_WSS);
const api = await ApiPromise.create({ provider: wsProvider });
await api.isReady;

await api.tx.tokens.transfer(address, pendulumCurrencyId, amountRaw).signAndSend(fundingAccountKeypair);

return res.status(200).json({ message: 'Subsidy transferred successfully' });
Expand Down
21 changes: 21 additions & 0 deletions signer-service/src/api/helpers/memoDerivation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { keccak256 } = require('viem/utils');
const { Keyring } = require('@polkadot/api');

// Returns the hash value for the address. If it's a polkadot address, it will return raw data of the address.
function getHashValueForAddress(address) {
if (address.startsWith('0x')) {
return address;
} else {
const keyring = new Keyring({ type: 'sr25519' });
return keyring.decodeAddress(address);
}
}

//A memo derivation.
async function deriveMemoFromAddress(address) {
const hashValue = getHashValueForAddress(address);
const hash = keccak256(hashValue);
return BigInt(hash).toString().slice(0, 15);
}

module.exports = { deriveMemoFromAddress };
53 changes: 53 additions & 0 deletions signer-service/src/api/helpers/siweMessageFormatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
class SignInMessage {
// fixed statement string
static LOGIN_MESSAGE = ' wants you to sign in with your account: ';

constructor(fields) {
this.scheme = fields.scheme;
this.domain = fields.domain;
this.address = fields.address;
this.nonce = fields.nonce;
this.expirationTime = new Date(fields.expirationTime).toISOString();
this.issuedAt = fields.issuedAt ? new Date(fields.issuedAt).toISOString() : new Date().toISOString();
}

toMessage() {
const header = `${this.domain}${SignInMessage.LOGIN_MESSAGE}${this.address}`;

const body = `\nNonce: ${this.nonce}\nIssued At: ${this.issuedAt}\nExpiration Time: ${this.expirationTime}`;

return `${header}\n\n${body}`;
}

static fromMessage(message) {
const lines = message
.split('\n')
.map((l) => l.trim())
.filter((l) => l.length > 0);

const headerLine = lines.find((line) => line.includes(SignInMessage.LOGIN_MESSAGE)) || '';
const [domain, address] = headerLine.split(SignInMessage.LOGIN_MESSAGE).map((part) => part.trim());

const nonceLine = lines.find((line) => line.startsWith('Nonce:')) || '';
const nonce = nonceLine.split('Nonce:')[1]?.trim() || '';

const issuedAtLine = lines.find((line) => line.startsWith('Issued At:')) || '';
const issuedAt = issuedAtLine.split('Issued At:')[1]?.trim(); // Can't really be empty. Constructor will default to current date if not defined.
const issuedAtMilis = new Date(issuedAt).getTime();

const expirationTimeLine = lines.find((line) => line.startsWith('Expiration Time:')) || '';
const expirationTime = expirationTimeLine.split('Expiration Time:')[1]?.trim();
const expirationTimeMilis = new Date(expirationTime).getTime();

return new SignInMessage({
scheme: 'https',
domain,
address,
nonce,
expirationTime: expirationTimeMilis,
issuedAt: issuedAtMilis,
});
}
}

module.exports = { SignInMessage };
Loading

0 comments on commit 8aa829d

Please sign in to comment.