Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copilot siwe #204

Merged
merged 68 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
804ec26
feat(copilot): introduce redesign to trading copilot
MateuszStawski Nov 24, 2024
130aeb5
chore(copilot): adjust styling and change used components
MateuszStawski Nov 28, 2024
67f20d0
chore(styling): change p class to text-label3
MateuszStawski Nov 28, 2024
053e504
Merge branch 'master' into feat/introduce-copliot-redesign
MateuszStawski Nov 28, 2024
6713e15
fix(copilot): change improper onclick function argument
MateuszStawski Nov 28, 2024
be32188
Merge branch 'feat/introduce-copliot-redesign' of https://github.com/…
MateuszStawski Nov 28, 2024
1ea1b74
chore(lint): adjust format
MateuszStawski Nov 28, 2024
7a8a4b5
build: resolve conflicts
MateuszStawski Nov 29, 2024
a0b9556
chore: remove unused export
MateuszStawski Nov 30, 2024
239363e
chore: remove dialog component and its folder
MateuszStawski Nov 30, 2024
d838193
refactor/feat: update mismatched classnames & add new background variant
MateuszStawski Dec 4, 2024
b8a3195
refactor: update styles to match appearance on figma
MateuszStawski Dec 5, 2024
29cd3dc
refactor: delete duplicated icon button
MateuszStawski Dec 5, 2024
e00c2e8
WiP
SolutionsEngineer Dec 5, 2024
6822109
fix: update wrong avatar border class
MateuszStawski Dec 6, 2024
664a81b
feat(draft): connect trading copilot view to API
MateuszStawski Dec 6, 2024
bf671cf
fix: restoring the incorrectly changed class
MateuszStawski Dec 6, 2024
deb832b
Merge branch 'feat/introduce-copliot-redesign' into copilot-dev
MateuszStawski Dec 7, 2024
da3c122
Merge branch 'feat/trading-copilot-api-connection' into copilot-dev
MateuszStawski Dec 7, 2024
a59d4ed
refactor: code cleanup after merge
MateuszStawski Dec 7, 2024
2b13975
feat: completing the API connection for copilot trading view
MateuszStawski Dec 8, 2024
10d060c
Merge branch 'copilot-dev' of github.com:idriss-xyz/core into copilot…
MateuszStawski Dec 8, 2024
db92839
fix: revert wrong merge changes
MateuszStawski Dec 8, 2024
c7b9f38
fix: remove unused exports
MateuszStawski Dec 8, 2024
897a364
feat: fetch copilot subscriptions using user wallet address
MateuszStawski Dec 9, 2024
39207a8
feat: use already implemented notifications
MateuszStawski Dec 10, 2024
6eb9a84
feat: verify if notification is rendered to avoid duplicates
MateuszStawski Dec 10, 2024
cf88ec1
feat: render websocket swaps as toast and use wallet address as user id
MateuszStawski Dec 11, 2024
ae8e22d
feat: add transaction creation api, update copilot websocket & notifi…
MateuszStawski Dec 12, 2024
05836e3
refactor: remove unnecessary exports
MateuszStawski Dec 12, 2024
05d5802
fix/refactor: copilot dialogs, toasts and websocket
MateuszStawski Dec 13, 2024
398612b
feat: add handling of subscribing wallet via farcaster name
MateuszStawski Dec 16, 2024
9262e0f
fix: remove unused export
MateuszStawski Dec 16, 2024
7abd4d9
feat: round ballance numer in copilot dialog
MateuszStawski Dec 17, 2024
c288bca
fix: change dynamic token symbol to static ETH in copilot dialog
MateuszStawski Dec 17, 2024
65042de
feat: add value of trade in copilot dialog
MateuszStawski Dec 17, 2024
e7ee512
feat: fetch from api current value of trade in eth
MateuszStawski Dec 17, 2024
8fc686f
feat: send copilot quotes in wei
MateuszStawski Dec 17, 2024
cc3940c
fix: temporary fix of rendering saved notifications before extension …
MateuszStawski Dec 18, 2024
e166e3e
add Creator tag to messages (#201)
lennardevertz Dec 18, 2024
624c8f3
feat(copilot): Add get-siwe-message command
daniel0ar Dec 20, 2024
1d7fdac
Merge branch 'copilot-dev' into feat/copilot-SIWE
daniel0ar Dec 20, 2024
98b16ac
feat(copilot): Create SIWE message on /wallet-address endpoint
daniel0ar Dec 20, 2024
7411607
feat(copilot): Add SIWE message verification
daniel0ar Dec 20, 2024
681def9
feat(copilot): Add exports for GetSiweMessageCommand
daniel0ar Dec 20, 2024
99cf655
feat: add complete handling of transaction in copilot modal
MateuszStawski Dec 21, 2024
9e7d213
feat: update success dialog heading in copilot
MateuszStawski Dec 21, 2024
cbd6808
feat: reload socket after changing user wallet
MateuszStawski Dec 21, 2024
5476954
Merge branch 'copilot-dev' of github.com:idriss-xyz/core into copilot…
MateuszStawski Dec 21, 2024
b85f713
fix: use wallet address to register websocket instead of id1
MateuszStawski Dec 21, 2024
aeac8f8
feat: add minimum height for copilot modal
MateuszStawski Dec 22, 2024
194f032
fix: update class selector to block github shortcuts
MateuszStawski Dec 23, 2024
cac9aab
feat(copilot): Add generate-siwe-message hook
daniel0ar Dec 23, 2024
934094d
refactor: update variables and texts, delete unused code
MateuszStawski Dec 26, 2024
823de70
feat: add time counter and update styles to match whole project
MateuszStawski Dec 27, 2024
919b24e
fix: add transport url to other two commands using public client
MateuszStawski Dec 27, 2024
1527058
fix: remove unused export of formatted time difference
MateuszStawski Dec 27, 2024
472540c
fix: remove unused export in date-utils
MateuszStawski Dec 27, 2024
0e180d2
feat: add logging in to api using siwe
MateuszStawski Dec 28, 2024
70e6d60
Merge branch 'copilot-dev' into copilot-SIWE
MateuszStawski Dec 28, 2024
bc89e2c
feat: add logging in to api in copilot form onSubmits
MateuszStawski Dec 28, 2024
8b7bc3c
fix: use wallet address instead of id1 in websocket connection
MateuszStawski Dec 30, 2024
8e82c1a
fix: refine scraping methods for warpcast after their structural chan…
21142 Dec 30, 2024
997c6a4
Token section (#209)
lennardevertz Jan 2, 2025
1f912f9
fix: update login via siwe to use proper domain
MateuszStawski Jan 3, 2025
512b6ee
Merge branch 'master' into copilot-SIWE
MateuszStawski Jan 3, 2025
c30ecae
Merge branch 'copilot-dev' into copilot-SIWE
MateuszStawski Jan 6, 2025
8d2916f
fix: cleanup code after merge
MateuszStawski Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/copilot-api/config/publicClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

export const publicClient = createPublicClient({
chain: mainnet,
transport: http('https://rpc.payload.de')
})
75 changes: 39 additions & 36 deletions apps/copilot-api/routes/auth.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import express from 'express';
import type {Request, Response} from 'express';
import type { Request, Response } from 'express';
import dotenv from 'dotenv';
import jwt from 'jsonwebtoken';
import {throwInternalError} from '../middleware/error.middleware';
import {isAddress, verifyMessage} from 'viem';
import {dataSource} from '../db';
import {AddressesEntity} from '../entities/addreesses.entity';
import {UsersEntity} from '../entities/users.entity';
import {v4 as uuidv4} from 'uuid';
import { throwInternalError } from '../middleware/error.middleware';
import { isAddress } from 'viem';
import { dataSource } from '../db';
import { AddressesEntity } from '../entities/addreesses.entity';
import { UsersEntity } from '../entities/users.entity';
import { createSiweMessage, generateSiweNonce } from 'viem/siwe';
import { publicClient } from '../config/publicClient';

dotenv.config();

Expand All @@ -17,31 +18,31 @@ const addressesRepo = dataSource.getRepository(AddressesEntity);
const usersRepo = dataSource.getRepository(UsersEntity);

router.post('/login', async (req: Request, res: Response) => {
const {signature, walletAddress, challengeMessage} = req.body;
const { signature, walletAddress, message } = req.body;

if (!isAddress(walletAddress)) {
res.status(403).json({error: 'Invalid wallet address'});
res.status(403).json({ error: 'Invalid wallet address' });
return;
}

try {
const valid_address = await verifyMessage({
signature,
const valid = await publicClient.verifySiweMessage({
address: walletAddress,
message: challengeMessage
message,
signature,
});

if (!valid_address) {
res.status(403).json({error: 'Invalid signature'});
if (!valid) {
res.status(403).json({ error: 'Invalid signature' });
return;
}

const existingAddress = await addressesRepo.findOne({
where: {address: walletAddress},
where: { address: walletAddress },
});

const user = await usersRepo.findOne({
where: {uuid: existingAddress?.userId},
where: { uuid: existingAddress?.userId },
});

if (!user) {
Expand All @@ -56,7 +57,7 @@ router.post('/login', async (req: Request, res: Response) => {
expiresIn: '7d',
});

res.status(200).send({token});
res.status(200).send({ token });
return;
}

Expand All @@ -70,42 +71,44 @@ router.post('/login', async (req: Request, res: Response) => {
expiresIn: '7d',
});

res.status(200).send({token});
} catch (err) {
}
res.status(200).send({ token });
} catch (err) {}
});

router.post('/wallet-address', async (req, res) => {
try {
const {walletAddress} = req.body;
const nonce = uuidv4();
const timestamp = new Date().toISOString();
const challengeMessage = `
Challenge: ${process.env.CHALLENGE_SECRET},
Wallet Address: ${walletAddress},
Nonce: ${nonce},
Timestamp: ${timestamp}
`
.replace(/\\s+/g, ' ')
.trim();
res.status(200).json({nonce, challengeMessage});
const { walletAddress, chainId, domain } = req.body;
const nonce = generateSiweNonce();
const timestamp = new Date();

const message = createSiweMessage({
address: walletAddress,
chainId,
domain,
nonce,
uri: `https://${domain}`, // TODO: Change for production
version: '1',
issuedAt: timestamp,
});

res.status(200).json({ nonce, message });
} catch (err) {
throwInternalError(res, 'Error generating challenge message: ', err);
throwInternalError(res, 'Error generating login message: ', err);
}
});

router.post('/verify-token', async (req, res) => {
const {token} = req.body;
const { token } = req.body;

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET!);

const id: number = (decoded as Request)['user'].id;

const user = await usersRepo.findOne({where: {uuid: id}});
const user = await usersRepo.findOne({ where: { uuid: id } });

if (!user) {
res.status(401).json({error: 'Invalid token'});
res.status(401).json({ error: 'Invalid token' });
return;
}

Expand Down
6 changes: 4 additions & 2 deletions apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
"@amplitude/analytics-browser": "2.9.2",
"@ebay/nice-modal-react": "^1.2.13",
"@hookform/resolvers": "^3.9.0",
"@noble/hashes": "^1.5.0",
"@idriss-xyz/ui": "workspace:*",
"@idriss-xyz/constants": "workspace:*",
"@idriss-xyz/ui": "workspace:*",
"@idriss-xyz/wallet-connect": "workspace:*",
"@lifi/sdk": "^3.4.2",
"@noble/hashes": "^1.5.0",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
Expand All @@ -50,6 +51,7 @@
"react-number-format": "^5.4.2",
"react-router": "^6.27.0",
"react-use": "^17.5.1",
"socket.io-client": "^4.8.1",
"tailwind-merge": "^2.5.4",
"ts-custom-error": "^3.3.1",
"ts-pattern": "^5.5.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback, useEffect, useState } from 'react';
import { ScrollArea } from '@idriss-xyz/ui/scroll-area';

import { classes, ScrollArea } from 'shared/ui';
import { classes } from 'shared/ui';

import { SearchResult } from '../types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import {
Command,
FailureResult,
HandlerError,
HandlerResponseError,
OkResult,
} from 'shared/messaging';

import { Subscription } from '../types';
import { TradingCopilotSettingsManager } from '../subscriptions-manager';
import { SubscriptionRequest as Payload } from '../types';

interface Payload {
subscription: Subscription;
}
import { COPILOT_API_URL } from './constants';

type Response = boolean;

Expand All @@ -26,9 +24,26 @@ export class AddTradingCopilotSubscriptionCommand extends Command<

async handle() {
try {
await TradingCopilotSettingsManager.subscribe(this.payload.subscription);
const response = await fetch(`${COPILOT_API_URL}/subscribe`, {
method: 'POST',
body: JSON.stringify(this.payload),
headers: {
'Content-Type': 'application/json',
},
});

if (!response.ok) {
const responseText = await response.text();
throw new HandlerResponseError(
this.name,
responseText,
response.status,
);
}

const json = (await response.json()) as Response;

return new OkResult(true);
return new OkResult(json);
} catch (error) {
this.captureException(error);
if (error instanceof HandlerError) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const COPILOT_API_URL = 'https://copilot-production-e887.up.railway.app';
export const QUOTE_API_URL = 'https://idriss-lifi.vercel.app/api/get-quote';
export const AUTH_API_URL = 'http://localhost:8080/auth';
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class GetEnsAddressCommand extends Command<Payload, Hex | null> {
try {
const client = createPublicClient({
chain: { ...mainnet },
transport: http(),
transport: http('https://eth.llamarpc.com'),
});
const response = await client.getEnsAddress({
name: normalize(this.payload.ensName),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createPublicClient, formatEther, http } from 'viem';
import { mainnet } from 'viem/chains';

import { Hex } from 'shared/web3';
import {
Command,
FailureResult,
HandlerError,
OkResult,
} from 'shared/messaging';

type Payload = {
address: Hex;
blockTag: 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
};

export class GetEnsBalanceCommand extends Command<Payload, string | null> {
public readonly name = 'GetEnsBalanceCommand' as const;

constructor(public payload: Payload) {
super();
}

async handle() {
try {
const client = createPublicClient({
chain: { ...mainnet },
transport: http('https://eth.llamarpc.com'),
});

const result = await client.getBalance(this.payload);
const balanceAsEth = formatEther(result);

return new OkResult(balanceAsEth);
} catch (error) {
this.captureException(error);
if (error instanceof HandlerError) {
return new FailureResult(error.message);
}

return new FailureResult();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class GetEnsInfoCommand extends Command<Payload, string | null> {
try {
const client = createPublicClient({
chain: { ...mainnet },
transport: http(),
transport: http('https://eth.llamarpc.com'),
});

const result = await client.getEnsText({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';

import { Hex } from 'shared/web3';
import {
Command,
FailureResult,
HandlerError,
OkResult,
} from 'shared/messaging';

type Payload = {
address: Hex;
};

export class GetEnsNameCommand extends Command<Payload, string | null> {
public readonly name = 'GetEnsNameCommand' as const;

constructor(public payload: Payload) {
super();
}

async handle() {
try {
const client = createPublicClient({
chain: { ...mainnet },
transport: http('https://eth.llamarpc.com'),
});
const result = await client.getEnsName(this.payload);

return new OkResult(result);
} catch (error) {
this.captureException(error);
if (error instanceof HandlerError) {
return new FailureResult(error.message);
}

return new FailureResult();
}
}
}
Loading
Loading