Skip to content

Commit bd0010d

Browse files
authored
Merge pull request #358 from pendulum-chain/polygon-prototype-staging
Create new production release
2 parents 8aa829d + 6fc62c7 commit bd0010d

File tree

100 files changed

+2381
-1221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+2381
-1221
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ docs/
99
.lighthouseci/
1010
**/coins/*
1111
*.yml
12+
*.sol
1213

1314
package-lock.json
1415
package.json

_redirects

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
/api/production/* https://prototype-signer-service-polygon.pendulumchain.tech/:splat 200
22
/api/staging/* https://prototype-signer-service-polygon-staging.pendulumchain.tech/:splat 200
3-
/* /index.html 200
3+
/* /index.html 200

index.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="en" class="notranslate" translate="no">
33
<head>
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/png" href="/favicon.png" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>Vortex</title>
88
<link rel="preconnect" href="https://fonts.googleapis.com" />
99
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10+
<meta name="google" content="notranslate" />
1011

1112
<!-- Google Tag Manager -->
1213
<script>
@@ -35,14 +36,14 @@
3536

3637
<body style="background-color: #fff">
3738
<!-- Google Tag Manager (noscript) -->
38-
<noscript
39-
><iframe
39+
<noscript>
40+
<iframe
4041
src="https://www.googletagmanager.com/ns.html?id=GTM-T8JZSLD8"
4142
height="0"
4243
width="0"
4344
style="display: none; visibility: hidden"
44-
></iframe
45-
></noscript>
45+
></iframe>
46+
</noscript>
4647
<!-- End Google Tag Manager (noscript) -->
4748

4849
<div id="app"></div>

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
"@reown/appkit-adapter-wagmi": "^1.3.1",
3939
"@sentry/react": "^8.36.0",
4040
"@sentry/vite-plugin": "^2.22.6",
41+
"@slack/web-api": "^7.7.0",
4142
"@talismn/connect-components": "^1.1.9",
43+
"@talismn/connect-wallets": "^1.2.5",
4244
"@tanstack/react-query": "^5.61.0",
4345
"@walletconnect/modal": "^2.6.2",
4446
"@walletconnect/universal-provider": "^2.12.2",
@@ -63,7 +65,8 @@
6365
"viem": "^2.21.43",
6466
"wagmi": "^2.12.29",
6567
"web3": "^4.10.0",
66-
"yup": "^1.4.0"
68+
"yup": "^1.4.0",
69+
"zustand": "^5.0.2"
6770
},
6871
"devDependencies": {
6972
"@babel/core": "^7.20.12",

signer-service/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The following environment variables are available to configure the service.
2525
- `FUNDING_SECRET`: Secret key to sign the funding transactions on Stellar.
2626
- `PENDULUM_FUNDING_SEED`: Seed phrase to sign the funding transactions on Pendulum.
2727
- `MOONBEAM_EXECUTOR_PRIVATE_KEY`: Private key to sign the transactions on Moonbeam.
28+
- `SLACK_WEB_HOOK_TOKEN` - Slack web hook token for error reporting.
2829

2930
### Optional
3031

signer-service/src/api/controllers/moonbeam.controller.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {
88
MOONBEAM_RECEIVER_CONTRACT_ADDRESS,
99
MOONBEAM_FUNDING_AMOUNT_UNITS,
1010
} = require('../../constants/constants');
11+
const { SlackNotifier } = require('../services/slack.service');
1112
const splitReceiverABI = require('../../../../mooncontracts/splitReceiverABI.json');
1213

1314
exports.executeXcmController = async (req, res) => {
@@ -54,6 +55,7 @@ exports.executeXcmController = async (req, res) => {
5455
};
5556

5657
exports.sendStatusWithPk = async () => {
58+
const slackService = new SlackNotifier();
5759
let moonbeamExecutorAccount;
5860

5961
try {
@@ -66,12 +68,16 @@ exports.sendStatusWithPk = async () => {
6668
const balance = await publicClient.getBalance({ address: moonbeamExecutorAccount.address });
6769

6870
// We are checking if the balance is less than 10 GLMR
69-
const minimum_balance = Big(MOONBEAM_FUNDING_AMOUNT_UNITS).times(Big(10).pow(18));
70-
if (balance < minimum_balance) {
71+
const minimumBalance = Big(MOONBEAM_FUNDING_AMOUNT_UNITS).times(Big(10).pow(18));
72+
73+
if (balance < minimumBalance) {
74+
slackService.sendMessage({
75+
text: `Current balance of funding account is ${balance} GLMR please charge the account ${moonbeamExecutorAccount.address}.`,
76+
});
7177
return { status: false, public: moonbeamExecutorAccount.address };
72-
} else {
73-
return { status: true, public: moonbeamExecutorAccount.address };
7478
}
79+
80+
return { status: true, public: moonbeamExecutorAccount.address };
7581
} catch (error) {
7682
console.error('Error fetching Moonbeam executor balance:', error);
7783
return { status: false, public: moonbeamExecutorAccount?.address };

signer-service/src/api/routes/v1/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const { sendStatusWithPk: sendStellarStatusWithPk } = require('../../services/st
1515
const { sendStatusWithPk: sendPendulumStatusWithPk } = require('../../services/pendulum.service');
1616
const { sendStatusWithPk: sendMoonbeamStatusWithPk } = require('../../controllers/moonbeam.controller');
1717

18-
async function sendStatusWithPk(req, res, next) {
18+
async function sendStatusWithPk(_, res) {
1919
const stellar = await sendStellarStatusWithPk();
2020
const pendulum = await sendPendulumStatusWithPk();
2121
const moonbeam = await sendMoonbeamStatusWithPk();

signer-service/src/api/services/alchemypay.service.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@ function getAlchemyPayNetworkCode(network) {
190190
switch (network.toUpperCase()) {
191191
case 'POLYGON':
192192
return 'MATIC';
193+
case 'BSC':
194+
return 'BSC';
195+
case 'ARBITRUM':
196+
return 'ARBITRUM';
197+
case 'AVALANCHE':
198+
return 'AVAX';
199+
case 'ETHEREUM':
200+
return 'ETH';
193201
default:
194202
return network;
195203
}

signer-service/src/api/services/pendulum.service.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {
88
PENDULUM_EPHEMERAL_STARTING_BALANCE_UNITS,
99
} = require('../../constants/constants');
1010
const { TOKEN_CONFIG } = require('../../constants/tokenConfig');
11+
const { SlackNotifier } = require('./slack.service');
1112

1213
require('dotenv').config();
1314

@@ -21,6 +22,14 @@ function multiplyByPowerOfTen(bigDecimal, power) {
2122
return newBigDecimal;
2223
}
2324

25+
function divideByPowerOfTen(bigDecimal, power) {
26+
const newBigDecimal = new Big(bigDecimal);
27+
if (newBigDecimal.c[0] === 0) return newBigDecimal;
28+
29+
newBigDecimal.e -= power;
30+
return newBigDecimal;
31+
}
32+
2433
let api;
2534
let previousSpecVersion;
2635

@@ -82,7 +91,16 @@ exports.fundEphemeralAccount = async (ephemeralAddress) => {
8291
}
8392
};
8493

94+
const ChainDecimals = 12;
95+
96+
const nativeToDecimal = (value, decimals = ChainDecimals) => {
97+
const divisor = new Big(10).pow(decimals);
98+
99+
return value.div(divisor);
100+
};
101+
85102
exports.sendStatusWithPk = async () => {
103+
const slackNotifier = new SlackNotifier();
86104
const apiData = await createPolkadotApi();
87105
const { fundingAccountKeypair } = getFundingData(apiData.ss58Format, apiData.decimals);
88106
const { data: balance } = await apiData.api.query.system.account(fundingAccountKeypair.address);
@@ -109,14 +127,28 @@ exports.sendStatusWithPk = async () => {
109127
if (remainingMaxSubsidiesAvailable.lt(SUBSIDY_MINIMUM_RATIO_FUND_UNITS)) {
110128
isTokensSufficient = false;
111129
console.log(`Token ${token} balance is insufficient.`);
130+
131+
slackNotifier.sendMessage({
132+
text: `Current balance of funding account is ${nativeToDecimal(
133+
tokenBalance,
134+
).toString()} ${token} please charge the account ${fundingAccountKeypair.address}.`,
135+
});
112136
}
113137
}),
114138
);
115139

116140
const minimumBalanceFundingAccount = multiplyByPowerOfTen(Big(PENDULUM_FUNDING_AMOUNT_UNITS), apiData.decimals);
117141
const nativeBalance = Big(balance?.free?.toString() ?? '0');
142+
118143
if (nativeBalance.gte(minimumBalanceFundingAccount) && isTokensSufficient) {
119144
return { status: true, public: fundingAccountKeypair.address };
120145
}
146+
if (nativeBalance.lt(minimumBalanceFundingAccount)) {
147+
slackNotifier.sendMessage({
148+
text: `Current balance of funding account is ${nativeToDecimal(
149+
nativeBalance,
150+
).toString()} PEN please charge the account ${fundingAccountKeypair.address}.`,
151+
});
152+
}
121153
return { status: false, public: fundingAccountKeypair.address };
122154
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Store last message timestamps with their message signatures
2+
const messageHistory = new Map();
3+
// 6 hours in milliseconds
4+
const cooldownPeriod = 6 * 60 * 60 * 1000;
5+
6+
class SlackNotifier {
7+
constructor() {
8+
if (process.env.SLACK_WEB_HOOK_TOKEN) {
9+
this.webhookUrl = `https://hooks.slack.com/services/${process.env.SLACK_WEB_HOOK_TOKEN}`;
10+
} else {
11+
throw new Error('SLACK_WEB_HOOK_TOKEN is not defined');
12+
}
13+
}
14+
15+
generateMessageSignature(message) {
16+
// Create a unique signature for the message
17+
return JSON.stringify(message);
18+
}
19+
20+
isMessageAllowed(signature) {
21+
const now = Date.now();
22+
const lastSent = messageHistory.get(signature);
23+
24+
if (!lastSent) return true;
25+
26+
return now - lastSent >= cooldownPeriod;
27+
}
28+
29+
async sendMessage(message) {
30+
const signature = this.generateMessageSignature(message);
31+
32+
if (!this.isMessageAllowed(signature)) {
33+
// Message is still in cooldown period, skip sending
34+
return;
35+
}
36+
37+
const payload = JSON.stringify(message);
38+
39+
const response = await fetch(this.webhookUrl, {
40+
method: 'POST',
41+
headers: {
42+
'Content-Type': 'application/json',
43+
},
44+
body: payload,
45+
});
46+
47+
if (!response.ok) {
48+
throw new Error(`Failed to send message. Status: ${response.status}`);
49+
}
50+
51+
// Update the timestamp for this message
52+
messageHistory.set(signature, Date.now());
53+
}
54+
}
55+
56+
exports.SlackNotifier = SlackNotifier;

signer-service/src/api/services/stellar.service.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const {
66
STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS,
77
} = require('../../constants/constants');
88
const { TOKEN_CONFIG, getTokenConfigByAssetCode } = require('../../constants/tokenConfig');
9+
const { SlackNotifier } = require('./slack.service');
10+
911
// Derive funding pk
1012
const FUNDING_PUBLIC_KEY = Keypair.fromSecret(FUNDING_SECRET).publicKey();
1113
const horizonServer = new Horizon.Server(HORIZON_URL);
@@ -132,14 +134,19 @@ async function buildPaymentAndMergeTx(
132134
}
133135

134136
async function sendStatusWithPk() {
137+
const slackNotifier = new SlackNotifier();
138+
let stellarBalance = null;
139+
135140
try {
136141
// ensure the funding account exists
137-
const horizonServer = new Horizon.Server(HORIZON_URL);
138-
let account = await horizonServer.loadAccount(FUNDING_PUBLIC_KEY);
139-
let stellarBalance = account.balances.find((balance) => balance.asset_type === 'native');
142+
const account = await horizonServer.loadAccount(FUNDING_PUBLIC_KEY);
143+
stellarBalance = account.balances.find((balance) => balance.asset_type === 'native');
140144

141145
// ensure we have at the very least 10 XLM in the account
142146
if (Number(stellarBalance.balance) < STELLAR_FUNDING_AMOUNT_UNITS) {
147+
slackNotifier.sendMessage({
148+
text: `Current balance of funding account is ${stellarBalance.balance} XLM please charge the account ${FUNDING_PUBLIC_KEY}.`,
149+
});
143150
return { status: false, public: FUNDING_PUBLIC_KEY };
144151
}
145152

signer-service/src/api/services/transak.service.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@ async function priceQuery(cryptoCurrency, fiatCurrency, cryptoAmount, network, i
4545
// Helper function to get the network code for Transak. It seems like Transak just uses the commonly known network names
4646
// as the code for the network parameter in their API so we just return the network as is.
4747
function getTransakNetworkCode(network) {
48-
switch (network.toUpperCase()) {
49-
case 'POLYGON':
50-
return 'polygon';
51-
default:
52-
return network;
53-
}
48+
return network.toLowerCase();
5449
}
5550

5651
function getCryptoCode(fromCrypto) {

signer-service/src/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const { Keypair } = require('stellar-sdk');
21
const { port, env } = require('./config/vars');
32
const logger = require('./config/logger');
43
const app = require('./config/express');

src/assets/chains/arbitrum.svg

Lines changed: 37 additions & 0 deletions
Loading

src/assets/chains/avalanche.svg

Lines changed: 4 additions & 0 deletions
Loading

src/assets/chains/base.svg

Lines changed: 4 additions & 0 deletions
Loading

src/assets/chains/bsc.svg

Lines changed: 9 additions & 0 deletions
Loading

src/assets/chains/ethereum.svg

Lines changed: 15 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)