Skip to content
This repository was archived by the owner on Jun 19, 2024. It is now read-only.

Commit bdcdeab

Browse files
committed
feat: telegram webapps support (#158)
1 parent 132748d commit bdcdeab

23 files changed

+571
-180
lines changed

api/storage/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
"web3.storage": "4.5.4"
1111
},
1212
"devDependencies": {
13-
"@vercel/node": "2.10.3"
13+
"@vercel/node": "2.12.0"
1414
}
1515
}

api/storage/validate-hash.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { webcrypto } from 'crypto';
2+
import type { NextApiRequest, NextApiResponse } from 'next';
3+
4+
type Data = { ok: boolean } | { error: string };
5+
6+
async function isHashValid(data: Record<string, string>, botToken: string) {
7+
const encoder = new TextEncoder();
8+
9+
const checkString = Object.keys(data)
10+
.filter((key) => key !== `hash`)
11+
.map((key) => `${key}=${data[key]}`)
12+
.sort()
13+
.join(`\n`);
14+
15+
const secretKey = await webcrypto.subtle.importKey(
16+
`raw`,
17+
encoder.encode(`WebAppData`),
18+
{ name: `HMAC`, hash: `SHA-256` },
19+
true,
20+
[`sign`],
21+
);
22+
23+
const secret = await webcrypto.subtle.sign(
24+
`HMAC`,
25+
secretKey,
26+
encoder.encode(botToken),
27+
);
28+
29+
const signatureKey = await webcrypto.subtle.importKey(
30+
`raw`,
31+
secret,
32+
{ name: `HMAC`, hash: `SHA-256` },
33+
true,
34+
[`sign`],
35+
);
36+
37+
const signature = await webcrypto.subtle.sign(
38+
`HMAC`,
39+
signatureKey,
40+
encoder.encode(checkString),
41+
);
42+
43+
const hex = Buffer.from(signature).toString(`hex`);
44+
45+
return data.hash === hex;
46+
}
47+
48+
export default async function handler(
49+
req: NextApiRequest,
50+
res: NextApiResponse<Data>,
51+
) {
52+
if (req.method !== `POST`) {
53+
return res.status(405).json({ error: `Method not allowed` });
54+
}
55+
56+
if (!req.body.hash) {
57+
return res.status(400).json({
58+
error: `Missing required field hash`,
59+
});
60+
}
61+
62+
if (!process.env.BOT_TOKEN) {
63+
return res.status(500).json({ error: `Internal server error` });
64+
}
65+
66+
const data = Object.fromEntries(new URLSearchParams(req.body.hash));
67+
const isValid = await isHashValid(data, process.env.BOT_TOKEN);
68+
69+
if (isValid) {
70+
return res.status(200).json({ ok: true });
71+
}
72+
73+
return res.status(403).json({ error: `Invalid hash` });
74+
}

api/storage/yarn.lock

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,35 @@
3535
dependencies:
3636
"@jridgewell/trace-mapping" "0.3.9"
3737

38-
"@edge-runtime/format@1.1.0":
39-
version "1.1.0"
40-
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-1.1.0.tgz#5a209221a8bae7791d6e465c480f146249d1e15f"
41-
integrity sha512-MkLDDtPhXZIMx83NykdFmOpF7gVWIdd6GBHYb8V/E+PKWvD2pK/qWx9B30oN1iDJ2XBm0SGDjz02S8nDHI9lMQ==
38+
"@edge-runtime/format@2.0.1":
39+
version "2.0.1"
40+
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-2.0.1.tgz#765295809ff6a0938da739e13ef327d95a418395"
41+
integrity sha512-aE+9DtBvQyg349srixtXEUNauWtIv5HTKPy8Q9dvG1NvpldVIvvhcDBI+SuvDVM8kQl8phbYnp2NTNloBCn/Yg==
4242

4343
"@edge-runtime/primitives@2.0.0":
4444
version "2.0.0"
4545
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-2.0.0.tgz#b4bf44f9cab36aee3027fe4c3ff3cc1d5713e155"
4646
integrity sha512-AXqUq1zruTJAICrllUvZcgciIcEGHdF6KJ3r6FM0n4k8LpFxZ62tPWVIJ9HKm+xt+ncTBUZxwgUaQ73QMUQEKw==
4747

48+
"@edge-runtime/primitives@2.1.2":
49+
version "2.1.2"
50+
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-2.1.2.tgz#8ff657f12a7f8c7fc4e3a0c10ec19356ef2d656d"
51+
integrity sha512-SR04SMDybALlhIYIi0hiuEUwIl0b7Sn+RKwQkX6hydg4+AKMzBNDFhj2nqHDD1+xkHArV9EhmJIb6iGjShwSzg==
52+
4853
"@edge-runtime/vm@2.0.0":
4954
version "2.0.0"
5055
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-2.0.0.tgz#9170d2d03761eff4e27687888c4b2d9af1f94c7d"
5156
integrity sha512-BOLrAX8IWHRXu1siZocwLguKJPEUv7cr+rG8tI4hvHgMdIsBWHJlLeB8EjuUVnIURFrUiM49lVKn8DRrECmngw==
5257
dependencies:
5358
"@edge-runtime/primitives" "2.0.0"
5459

60+
"@edge-runtime/vm@2.1.2":
61+
version "2.1.2"
62+
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-2.1.2.tgz#d760ce27b659c17c470b23453321769c08d213f5"
63+
integrity sha512-j4H5S26NJhYOyjVMN8T/YJuwwslfnEX1P0j6N2Rq1FaubgNowdYunA9nlO7lg8Rgjv6dqJ2zKuM7GD1HFtNSGw==
64+
dependencies:
65+
"@edge-runtime/primitives" "2.1.2"
66+
5567
"@ipld/car@^3.0.1", "@ipld/car@^3.1.4", "@ipld/car@^3.2.3":
5668
version "3.2.4"
5769
resolved "https://registry.yarnpkg.com/@ipld/car/-/car-3.2.4.tgz#115951ba2255ec51d865773a074e422c169fb01c"
@@ -269,32 +281,41 @@
269281
resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-6.7.1.tgz#94bccb959d9f2dcdecb7744c939b546073902373"
270282
integrity sha512-Ecc9oQBSVwk1suENcRcj1L6gQrUt4+0XA9oPFxrUpoFEk04lP/ZV3qAQPk+ex08N+vfUulYdqb+cmVTnwqsmqw==
271283

284+
"@vercel/error-utils@1.0.8":
285+
version "1.0.8"
286+
resolved "https://registry.yarnpkg.com/@vercel/error-utils/-/error-utils-1.0.8.tgz#5cefc4142820846d011cf048ddfb0afda81d484b"
287+
integrity sha512-s+f7jP2oH1koICbQ8e3K9hOpOeUct7rbCnF9qsNwXemq850wAh2e90tp9R6oYBM0BNpiLRRm+oG5zD2sCIm3HQ==
288+
272289
"@vercel/node-bridge@4.0.1":
273290
version "4.0.1"
274291
resolved "https://registry.yarnpkg.com/@vercel/node-bridge/-/node-bridge-4.0.1.tgz#e4f41188f61d9cd4e7c44de31d436dd447e1978c"
275292
integrity sha512-XEfKfnLGzlIBpad7eGNPql1HnMhoSTv9q3uDNC4axdaAC/kI5yvl8kXjuCPAXYvpbJnVQPpcSUC5/r5ap8F3jA==
276293

277-
"@vercel/node@2.10.3":
278-
version "2.10.3"
279-
resolved "https://registry.yarnpkg.com/@vercel/node/-/node-2.10.3.tgz#24a65d9f7e69161762c85df630601f3852308c26"
280-
integrity sha512-R6YwD7YTV4OPEjXnthTP2Zn96ZF2TAjmBhGKfYC9ZuqlmFzSxqyuHn+RUSkknkKBO46b4OzaNdi5XVnAdJizLA==
294+
"@vercel/node@2.12.0":
295+
version "2.12.0"
296+
resolved "https://registry.yarnpkg.com/@vercel/node/-/node-2.12.0.tgz#2eff4ffb04ae3ca19a7fd7e49e4f376791284abb"
297+
integrity sha512-QItQ4DjKrHqTMk/hmtX64V5RfDdp+fDoFzbSbPUICkIOHK3EBCJ5c/392Iv05AwSv+mJIALZUGRQz5o4HKvs6A==
281298
dependencies:
282299
"@edge-runtime/vm" "2.0.0"
283300
"@types/node" "14.18.33"
284301
"@vercel/build-utils" "6.7.1"
302+
"@vercel/error-utils" "1.0.8"
285303
"@vercel/node-bridge" "4.0.1"
286-
"@vercel/static-config" "2.0.15"
287-
edge-runtime "2.0.0"
304+
"@vercel/static-config" "2.0.16"
305+
async-listen "1.2.0"
306+
edge-runtime "2.1.4"
288307
esbuild "0.14.47"
289308
exit-hook "2.2.1"
290309
node-fetch "2.6.7"
310+
path-to-regexp "6.2.1"
311+
ts-morph "12.0.0"
291312
ts-node "10.9.1"
292313
typescript "4.3.4"
293314

294-
"@vercel/static-config@2.0.15":
295-
version "2.0.15"
296-
resolved "https://registry.yarnpkg.com/@vercel/static-config/-/static-config-2.0.15.tgz#a1e4d052e50cb9493071aaa2b4ca5e05c054fada"
297-
integrity sha512-A/N3ZGiOOMql9JArwBTIfhFngFtmVC7ndKQKp0FoFq8MO79AS5qBBtdpILS5QA71M5v+9CPjVkHxN6QweU55Xg==
315+
"@vercel/static-config@2.0.16":
316+
version "2.0.16"
317+
resolved "https://registry.yarnpkg.com/@vercel/static-config/-/static-config-2.0.16.tgz#2495325056e62b94925d8432b703bbf5625b06e5"
318+
integrity sha512-lULo+NWBMpTJb9kR4AwYYK/2e7wknTJO2iFxgYYOkG5i12WHgPhMnXDKrEOcotxctd0yPKx3TsWVGEXniNm63g==
298319
dependencies:
299320
ajv "8.6.3"
300321
json-schema-to-ts "1.6.4"
@@ -430,6 +451,16 @@ arrify@^1.0.1:
430451
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
431452
integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==
432453

454+
async-listen@1.2.0:
455+
version "1.2.0"
456+
resolved "https://registry.yarnpkg.com/async-listen/-/async-listen-1.2.0.tgz#861ab6f92e1703ba54498b10ddb9b5da7b69f363"
457+
integrity sha512-CcEtRh/oc9Jc4uWeUwdpG/+Mb2YUHKmdaTf0gUr7Wa+bfp4xx70HOb3RuSTJMvqKNB1TkdTfjLdrcz2X4rkkZA==
458+
459+
async-listen@2.0.3:
460+
version "2.0.3"
461+
resolved "https://registry.yarnpkg.com/async-listen/-/async-listen-2.0.3.tgz#be1be5a1b15e6007123e67275450fc4e84955e61"
462+
integrity sha512-WVLi/FGIQaXyfYyNvmkwKT1RZbkzszLLnmW/gFCc5lbVvN/0QQCWpBwRBk2OWSdkkmKRBc8yD6BrKsjA3XKaSw==
463+
433464
available-typed-arrays@^1.0.5:
434465
version "1.0.5"
435466
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
@@ -633,15 +664,15 @@ dns-over-http-resolver@^1.2.3:
633664
native-fetch "^3.0.0"
634665
receptacle "^1.3.2"
635666

636-
edge-runtime@2.0.0:
637-
version "2.0.0"
638-
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-2.0.0.tgz#4739e1c8f4237db8ad8a16db5f0e28cc6de16aab"
639-
integrity sha512-TmRJhKi4mlM1e+zgF4CSzVU5gJ1sWj7ia+XhVgZ8PYyYUxk4PPjJU8qScpSLsAbdSxoBghLxdMuwuCzdYLd1sQ==
667+
edge-runtime@2.1.4:
668+
version "2.1.4"
669+
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-2.1.4.tgz#aea4e103897f451f98a9094df26b07c4d1eb75b3"
670+
integrity sha512-SertKByzAmjm+MkLbFl1q0ko+/90V24dhZgQM8fcdguQaDYVEVtb6okEBGeg8IQgL1/JUP8oSlUIxSI/bvsVRQ==
640671
dependencies:
641-
"@edge-runtime/format" "1.1.0"
642-
"@edge-runtime/vm" "2.0.0"
672+
"@edge-runtime/format" "2.0.1"
673+
"@edge-runtime/vm" "2.1.2"
674+
async-listen "2.0.3"
643675
exit-hook "2.2.1"
644-
http-status "1.5.3"
645676
mri "1.2.0"
646677
picocolors "1.0.0"
647678
pretty-bytes "5.6.0"
@@ -1033,11 +1064,6 @@ hosted-git-info@^4.0.1:
10331064
dependencies:
10341065
lru-cache "^6.0.0"
10351066

1036-
http-status@1.5.3:
1037-
version "1.5.3"
1038-
resolved "https://registry.yarnpkg.com/http-status/-/http-status-1.5.3.tgz#9d1f6adcd1a609f535679f6e1b82811b96c3306e"
1039-
integrity sha512-jCClqdnnwigYslmtfb28vPplOgoiZ0siP2Z8C5Ua+3UKbx410v+c+jT+jh1bbI4TvcEySuX0vd/CfFZFbDkJeQ==
1040-
10411067
iconv-lite@^0.6.2:
10421068
version "0.6.3"
10431069
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -1842,6 +1868,11 @@ path-parse@^1.0.7:
18421868
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
18431869
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
18441870

1871+
path-to-regexp@6.2.1:
1872+
version "6.2.1"
1873+
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
1874+
integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
1875+
18451876
peer-id@^0.16.0:
18461877
version "0.16.0"
18471878
resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.16.0.tgz#0913062cfa4378707fe69c949b5720b3efadbf32"

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "algoworld-swapper",
33
"description": "Free and trustless ASA swapper, powered by Algorand ⚡️",
4-
"version": "0.9.4",
4+
"version": "1.0.1",
55
"private": true,
66
"author": "AlgoWorld <info@algoworld.io>",
77
"license": "GPL-3.0",
@@ -48,6 +48,7 @@
4848
"@randlabs/myalgo-connect": "1.4.2",
4949
"@reduxjs/toolkit": "1.9.3",
5050
"@txnlab/use-wallet": "1.2.11",
51+
"@vkruglikov/react-telegram-web-app": "1.8.0",
5152
"@walletconnect/client": "1.8.0",
5253
"algorand-walletconnect-qrcode-modal": "1.8.0",
5354
"algosdk": "2.2.0",
@@ -66,6 +67,7 @@
6667
"react-tsparticles": "2.9.3",
6768
"react-use": "17.4.0",
6869
"swr": "1.3.0",
70+
"telegram-webapps-types": "1.0.5",
6971
"tsparticles": "2.9.3"
7072
},
7173
"devDependencies": {

src/common/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import { ChainType } from '@/models/Chain';
2020
import { IpfsGateway } from '@/models/Gateway';
21-
import { PROVIDER_ID } from '@txnlab/use-wallet';
21+
import { PROVIDER_ID as WALLET_PROVIDER_ID } from '@txnlab/use-wallet';
2222

2323
export const CHAIN_TYPE: ChainType = process.env.NEXT_PUBLIC_CHAIN_TYPE
2424
? (process.env.NEXT_PUBLIC_CHAIN_TYPE.trim().toLowerCase() as ChainType)
@@ -99,4 +99,5 @@ export const PERFORM_SWAP_PERFORM_BUTTON_ID = `AWPerformSwapPerformButton`;
9999
export const PUBLIC_SWAPS_SEARCH_FIELD_ID = `AWPublicSwapsSearchField`;
100100
export const PUBLIC_SWAPS_SEARCH_BUTTON_ID = `AWPublicSwapsSearchButton`;
101101

102+
export const PROVIDER_ID = WALLET_PROVIDER_ID;
102103
export const WALLET_PROVIDER_IDS = [PROVIDER_ID.MYALGO, PROVIDER_ID.PERA];

src/components/Dialogs/ConfirmDialog.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import * as React from 'react';
2-
import { render } from '@testing-library/react';
32
import ConfirmDialog from './ConfirmDialog';
3+
import renderWithProviders from '@/__utils__/renderWithProviders';
44

55
describe(`ConfirmDialog`, () => {
66
it(`renders the correct content and handles the buttons correctly`, () => {
77
const setOpenMock = jest.fn();
88
const onConfirmMock = jest.fn();
99
const onSwapVisibilityChangeMock = jest.fn();
10-
const { getByText } = render(
10+
const { getByText } = renderWithProviders(
1111
<ConfirmDialog
1212
title="Test Dialog"
1313
open={true}

0 commit comments

Comments
 (0)