Skip to content

Commit

Permalink
Merge pull request #287 from pendulum-chain/polygon-prototype-staging
Browse files Browse the repository at this point in the history
Create new production release
  • Loading branch information
ebma authored Nov 19, 2024
2 parents 9d5d5f4 + b277d90 commit 8332dca
Show file tree
Hide file tree
Showing 63 changed files with 2,805 additions and 1,085 deletions.
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ preact/
internals/
docs/
.lighthouseci/

**/coins/*
*.yml

package-lock.json
package.json
yarn.lock
favicon.png
.prettierignore

CHANGELOG.md
**/*.svg
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"packageManager": "[email protected]+sha512.837566d24eec14ec0f5f1411adb544e892b3454255e61fdef8fd05f3429480102806bac7446bc9daff3896b01ae4b62d00096c7e989f1596f2af10b927532f39",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "tsc && vite build && cp -R src/assets/coins dist/assets/coins && echo '/* /index.html 200' | cat > dist/_redirects",
"preview": "vite preview",
"lint": "eslint . --ext .ts,.tsx",
Expand Down Expand Up @@ -34,7 +34,8 @@
"@polkadot/types": "^13.2.1",
"@polkadot/util": "^13.1.1",
"@polkadot/util-crypto": "^13.1.1",
"@rainbow-me/rainbowkit": "^2.1.7",
"@reown/appkit": "^1.3.1",
"@reown/appkit-adapter-wagmi": "^1.3.1",
"@sentry/react": "^8.36.0",
"@sentry/vite-plugin": "^2.22.6",
"@talismn/connect-components": "^1.1.8",
Expand All @@ -60,8 +61,8 @@
"stellar-sdk": "^11.3.0",
"tailwind": "^4.0.0",
"tailwindcss": "^3.4.3",
"viem": "2.x",
"wagmi": "^2.10.3",
"viem": "^2.21.43",
"wagmi": "^2.12.29",
"web3": "^4.10.0",
"yup": "^1.4.0"
},
Expand Down
52 changes: 52 additions & 0 deletions signer-service/src/api/controllers/quote.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require('dotenv').config();

const alchemyPayService = require('../services/alchemypay.service');
const transakService = require('../services/transak.service');
const moonpayService = require('../services/moonpay.service');

exports.SUPPORTED_PROVIDERS = ['alchemypay', 'moonpay', 'transak'];

exports.SUPPORTED_CRYPTO_CURRENCIES = ['usdc', 'usdce', 'usdc.e', 'usdt'];

exports.SUPPORTED_FIAT_CURRENCIES = ['eur', 'ars'];

exports.getQuoteForProvider = async (req, res, next) => {
const { provider, fromCrypto, toFiat, amount, network } = req.query;
try {
switch (provider.toLowerCase()) {
case 'alchemypay':
try {
const alchemyPayQuote = await alchemyPayService.getQuoteFor(fromCrypto, toFiat, amount, network);
return res.json(alchemyPayQuote);
} catch (error) {
// AlchemyPay's errors are not very descriptive, so we just return a generic error message
return res.status(500).json({ error: 'Could not get quote from AlchemyPay', details: error.message });
}
case 'moonpay':
try {
const moonpayQuote = await moonpayService.getQuoteFor(fromCrypto, toFiat, amount);
return res.json(moonpayQuote);
} catch (error) {
if (error.message === 'Token not supported') {
return res.status(404).json({ error: 'Token not supported' });
}
return res.status(500).json({ error: 'Could not get quote from Moonpay', details: error.message });
}
case 'transak':
try {
const transakQuote = await transakService.getQuoteFor(fromCrypto, toFiat, amount, network);
return res.json(transakQuote);
} catch (error) {
if (error.message === 'Token not supported') {
return res.status(404).json({ error: 'Token not supported' });
}
return res.status(500).json({ error: 'Could not get quote from Transak', details: error.message });
}
default:
return res.status(400).json({ error: 'Invalid provider' });
}
} catch (error) {
console.error('Server error:', error);
return res.status(500).json({ error: 'Server error', details: error.message });
}
};
15 changes: 15 additions & 0 deletions signer-service/src/api/controllers/stellar.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { Keypair } = require('stellar-sdk');
const { FUNDING_SECRET } = require('../../constants/constants');

const { buildCreationStellarTx, buildPaymentAndMergeTx, sendStatusWithPk } = require('../services/stellar.service');
const { signSep10Challenge } = require('../services/sep10.service');

// Derive funding pk
const FUNDING_PUBLIC_KEY = Keypair.fromSecret(FUNDING_SECRET).publicKey();
Expand Down Expand Up @@ -50,3 +51,17 @@ exports.changeOpTransaction = async (req, res, next) => {
return res.status(500).json({ error: 'Failed to process transaction', details: error.message });
}
};

exports.signSep10Challenge = async (req, res, next) => {
try {
let { clientSignature, clientPublic } = await signSep10Challenge(
req.body.challengeXDR,
req.body.outToken,
req.body.clientPublicKey,
);
return res.json({ clientSignature, clientPublic });
} catch (error) {
console.error('Error in signSep10Challenge:', error);
return res.status(500).json({ error: 'Failed to sign challenge', details: error.message });
}
};
4 changes: 2 additions & 2 deletions signer-service/src/api/controllers/subsidize.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const Big = require('big.js');

const { PENDULUM_WSS, PENDULUM_FUNDING_SEED } = require('../../constants/constants');

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

const TOKEN_TO_SWAP = 'usdc.axl';

Expand Down Expand Up @@ -49,7 +49,7 @@ exports.subsidizePostSwap = async (req, res) => {
const assetIssuerHex = `0x${Keypair.fromPublicKey(assetIssuer).rawPublicKey().toString('hex')}`;
const pendulumCurrencyId = {
Stellar: {
AlphaNum4: { code: assetCode.padEnd(4, '\0'), issuer: assetIssuerHex },
AlphaNum4: { code: getPaddedAssetCode(assetCode), issuer: assetIssuerHex },
},
};

Expand Down
22 changes: 22 additions & 0 deletions signer-service/src/api/helpers/anchors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const fetchTomlValues = async (tomlFileUrl) => {
const response = await fetch(tomlFileUrl);
if (response.status !== 200) {
throw new Error(`Failed to fetch TOML file: ${response.statusText}`);
}

const tomlFileContent = (await response.text()).split('\n');
const findValueInToml = (key) => {
const keyValue = tomlFileContent.find((line) => line.includes(key));
return keyValue?.split('=')[1].trim().replaceAll('"', '');
};

return {
signingKey: findValueInToml('SIGNING_KEY'),
webAuthEndpoint: findValueInToml('WEB_AUTH_ENDPOINT'),
sep24Url: findValueInToml('TRANSFER_SERVER_SEP0024'),
sep6Url: findValueInToml('TRANSFER_SERVER'),
kycServer: findValueInToml('KYC_SERVER'),
};
};

module.exports = { fetchTomlValues };
59 changes: 59 additions & 0 deletions signer-service/src/api/middlewares/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ const { TOKEN_CONFIG } = require('../../constants/tokenConfig');
const { DUMP_SHEET_HEADER_VALUES } = require('../controllers/storage.controller');
const { EMAIL_SHEET_HEADER_VALUES } = require('../controllers/email.controller');
const { RATING_SHEET_HEADER_VALUES } = require('../controllers/rating.controller');
const {
SUPPORTED_PROVIDERS,
SUPPORTED_CRYPTO_CURRENCIES,
SUPPORTED_FIAT_CURRENCIES,
} = require('../controllers/quote.controller');

const validateCreationInput = (req, res, next) => {
const { accountId, maxTime, assetCode } = req.body;
Expand All @@ -19,6 +24,42 @@ const validateCreationInput = (req, res, next) => {
next();
};

const validateQuoteInput = (req, res, next) => {
const { provider, fromCrypto, toFiat, amount, network } = req.query;

if (!provider || SUPPORTED_PROVIDERS.indexOf(provider.toLowerCase()) === -1) {
return res
.status(400)
.json({ error: 'Invalid provider. Supported providers are: ' + SUPPORTED_PROVIDERS.join(', ') });
}

if (!fromCrypto || SUPPORTED_CRYPTO_CURRENCIES.indexOf(fromCrypto.toLowerCase()) === -1) {
return res
.status(400)
.json({ error: 'Invalid fromCrypto. Supported currencies are: ' + SUPPORTED_CRYPTO_CURRENCIES.join(', ') });
}

if (!toFiat || SUPPORTED_FIAT_CURRENCIES.indexOf(toFiat.toLowerCase()) === -1) {
return res
.status(400)
.json({ error: 'Invalid toFiat. Supported currencies are: ' + SUPPORTED_FIAT_CURRENCIES.join(', ') });
}

if (!amount) {
return res.status(400).json({ error: 'Missing amount parameter' });
}

if (!network) {
return res.status(400).json({ error: 'Missing network parameter' });
}

if (isNaN(parseFloat(amount))) {
return res.status(400).json({ error: 'Invalid amount parameter. Not a number.' });
}

next();
};

const validateChangeOpInput = (req, res, next) => {
const { accountId, sequence, paymentData, maxTime, assetCode } = req.body;
if (!accountId || !sequence || !paymentData || !maxTime) {
Expand Down Expand Up @@ -98,13 +139,31 @@ const validatePostSwapSubsidizationInput = (req, res, next) => {
next();
};

const validateSep10Input = (req, res, next) => {
const { challengeXDR, outToken, clientPublicKey } = req.body;
if (!challengeXDR) {
return res.status(400).json({ error: 'Missing Anchor challenge: challengeXDR' });
}

if (!outToken) {
return res.status(400).json({ error: 'Missing offramp token identifier: outToken' });
}

if (!clientPublicKey) {
return res.status(400).json({ error: 'Missing Stellar ephemeral public key: clientPublicKey' });
}
next();
};

module.exports = {
validateChangeOpInput,
validateQuoteInput,
validateCreationInput,
validatePreSwapSubsidizationInput,
validatePostSwapSubsidizationInput,
validateStorageInput,
validateEmailInput,
validateRatingInput,
validateExecuteXCM,
validateSep10Input,
};
6 changes: 6 additions & 0 deletions signer-service/src/api/routes/v1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const storageRoutes = require('./storage.route');
const emailRoutes = require('./email.route');
const ratingRoutes = require('./rating.route');
const subsidizeRoutes = require('./subsidize.route');
const quoteRoutes = require('./quote.route');

const router = express.Router({ mergeParams: true });
const { sendStatusWithPk: sendStellarStatusWithPk } = require('../../services/stellar.service');
Expand Down Expand Up @@ -35,6 +36,11 @@ router.get('/status', sendStatusWithPk);
// Don't show docs for now.
// router.use("/docs", express.static("docs"));

/**
* GET v1/quotes
*/
router.use('/quotes', quoteRoutes);

/**
* POST v1/stellar
*/
Expand Down
9 changes: 9 additions & 0 deletions signer-service/src/api/routes/v1/quote.route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const express = require('express');
const controller = require('../../controllers/quote.controller');
const { validateQuoteInput } = require('../../middlewares/validators');

const router = express.Router({ mergeParams: true });

router.route('/').get(validateQuoteInput, controller.getQuoteForProvider);

module.exports = router;
4 changes: 3 additions & 1 deletion signer-service/src/api/routes/v1/stellar.route.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const express = require('express');
const controller = require('../../controllers/stellar.controller');
const { validateCreationInput, validateChangeOpInput } = require('../../middlewares/validators');
const { validateCreationInput, validateChangeOpInput, validateSep10Input } = require('../../middlewares/validators');

const router = express.Router({ mergeParams: true });

router.route('/create').post(validateCreationInput, controller.createStellarTransaction);

router.route('/payment').post(validateChangeOpInput, controller.changeOpTransaction);

router.route('/sep10').post(validateSep10Input, controller.signSep10Challenge);

module.exports = router;
Loading

0 comments on commit 8332dca

Please sign in to comment.