Skip to content

Commit 65eb243

Browse files
Add XUMM login for link wallet (#3)
* Add xumm login * Shared function to process link wallet logic * Bump version * Remove address in command if xumm login enabled
1 parent 8e0cad4 commit 65eb243

9 files changed

+750
-129
lines changed

package-lock.json

+438-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "XRPL-Discord-Bot",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "A customisable open-source Discord bot that brings the power of the XRPL to Discord communities.",
55
"repository": {
66
"type": "git",
@@ -26,13 +26,16 @@
2626
"@types/node": "^16.11.9",
2727
"applicationinsights": "^2.1.9",
2828
"axios": "^0.24.0",
29+
"body-parser": "^1.20.1",
2930
"discord-api-types": "^0.24.0",
3031
"discord.js": "^13.3.1",
3132
"eventemitter3": "^4.0.7",
3233
"express": "^4.17.1",
3334
"mongodb": "^3.6.2",
3435
"tslint": "^6.1.3",
3536
"typescript": "^4.0.3",
36-
"xrpl": "^2.0.2"
37+
"xrpl": "^2.0.2",
38+
"xrpl-txdata": "^1.2.1",
39+
"xumm-sdk": "^1.3.9"
3740
}
3841
}

src/app.ts

+22-9
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ if (SETTINGS.APPLICATION_INSIGHTS.ENABLED) {
88
const LOGGER = appInsights?.defaultClient ?? null;
99

1010
import express from 'express';
11+
import bodyParser from 'body-parser';
1112
import { Client, Intents, Message, Interaction } from 'discord.js';
1213
import EventFactory from './events/EventFactory';
1314
import { EventTypes } from './events/BotEvents';
14-
1515
import { scanLinkedWallets } from './business/scanLinkedWallets.js';
1616
import { scanLinkedAccounts } from './business/scanLinkedAccounts.js';
17+
import xummWebhook from './integration/xumm/webhook.js';
1718

1819
// Discord Client
1920
const discordClient = new Client({
@@ -35,14 +36,16 @@ const commands = [
3536
{
3637
name: 'linkwallet',
3738
description: 'Link your wallet to get server roles',
38-
options: [
39-
{
40-
type: 3,
41-
name: 'wallet-address',
42-
description: 'Your XRP Wallet Address',
43-
required: true,
44-
},
45-
],
39+
options: SETTINGS.XUMM.ENABLED
40+
? null
41+
: [
42+
{
43+
type: 3,
44+
name: 'wallet-address',
45+
description: 'Your XRP Wallet Address',
46+
required: true,
47+
},
48+
],
4649
},
4750
{
4851
name: 'price',
@@ -131,6 +134,16 @@ webServer.get('/updateAccounts', async (req, res) => {
131134
res.send(await scanLinkedAccounts(discordClient, LOGGER));
132135
});
133136

137+
webServer.use('/xummWebhook', bodyParser.json());
138+
139+
webServer.post('/xummWebhook', async (req, res) => {
140+
if (SETTINGS.XUMM.ENABLED) {
141+
await xummWebhook(req.body, discordClient);
142+
}
143+
144+
res.send({ status: 'OK' });
145+
});
146+
134147
webServer.listen(SETTINGS.APP.PORT, async () => {
135148
console.log(`Listening at http://localhost:${SETTINGS.APP.PORT}`);
136149
});
+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { getWalletHoldings } from '../integration/xrpl/getWalletHoldings.js';
2+
import { updateUserWallet } from '../data/updateUserWallet.js';
3+
import { updateUserRoles } from '../integration/discord/updateUserRoles.js';
4+
import { Client, User } from 'discord.js';
5+
import truncate from '../utils/truncate.js';
6+
import { WalletUpdateResponse } from '../models/enum/WalletUpdateResponse.js';
7+
8+
const linkWalletToDiscordAccount = async (
9+
walletAddress: string,
10+
verified: boolean,
11+
user: User,
12+
client: Client,
13+
LOGGER: any
14+
): Promise<string> => {
15+
if (!walletAddress) {
16+
return null;
17+
}
18+
19+
// Get holdings
20+
let holdings = await getWalletHoldings(walletAddress, null);
21+
if (holdings === -1) {
22+
if (LOGGER !== null) {
23+
LOGGER.trackEvent({
24+
name: 'linkWallet-no-trustline',
25+
properties: { walletAddress },
26+
});
27+
}
28+
29+
return `Seems like you don't have the project trustline yet, please retry once it has been added 👉 https://xrpscan.com/account/${walletAddress}`;
30+
}
31+
32+
// Allow them to set it even with network error
33+
let hadError = false;
34+
if (holdings === null) {
35+
hadError = true;
36+
holdings = 0;
37+
}
38+
39+
const newWallet: IWallet = {
40+
address: walletAddress,
41+
points: holdings,
42+
verified,
43+
};
44+
45+
const newUser: IBotUser = {
46+
discordId: user.id,
47+
discordUsername: user.username,
48+
discordDiscriminator: user.discriminator,
49+
previousDiscordUsername: '',
50+
previousDiscordDiscriminator: '',
51+
totalPoints: holdings,
52+
wallets: [],
53+
};
54+
55+
// Save in Mongo
56+
const mongoUpdateResult = await updateUserWallet(newUser, newWallet, false);
57+
58+
// The wallet has been claimed before, needs to be set by admin
59+
if (mongoUpdateResult === WalletUpdateResponse.ErrorAddressAlreadyClaimed) {
60+
if (LOGGER !== null) {
61+
LOGGER.trackEvent({
62+
name: 'linkWallet-claimed-by-another-user',
63+
properties: {
64+
walletAddress,
65+
activeUserId: user.id,
66+
activeUserName: user.username,
67+
},
68+
});
69+
}
70+
71+
return `This address has been claimed before, if it wasn't done by you please message a mod with ownership proof to claim it`;
72+
}
73+
74+
// If the user has set too many addresses an admin has to do it
75+
if (mongoUpdateResult === WalletUpdateResponse.ErrorTooManyAccountClaims) {
76+
if (LOGGER !== null) {
77+
LOGGER.trackEvent({
78+
name: 'linkWallet-too-many-claimed',
79+
properties: {
80+
walletAddress,
81+
activeUserId: user.id,
82+
activeUserName: user.username,
83+
},
84+
});
85+
}
86+
return `You seem to have claimed too many addresses, please message a mod with ownership proof to claim more`;
87+
}
88+
89+
// Set role
90+
await updateUserRoles(0, holdings, user.id, client, LOGGER, false);
91+
92+
if (LOGGER !== null) {
93+
LOGGER.trackEvent({
94+
name: 'linkWallet-success',
95+
properties: {
96+
walletAddress,
97+
activeUserId: user.id,
98+
activeUserName: user.username,
99+
},
100+
});
101+
}
102+
103+
// Send confirmation to the user
104+
if (hadError) {
105+
return `Wallet linked! There was an error trying to get your holdings from the XRPL network. Your role will be updated automatically once the network is working. You do not need to do anything else.`;
106+
}
107+
108+
return `Found your ${truncate(
109+
holdings,
110+
2
111+
)} points! Updated server roles set 🚀`;
112+
};
113+
114+
export { linkWalletToDiscordAccount };

src/commands/AdminLinkWallet.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const adminLinkWallet = async (message: Message, client: Client) => {
3838
const newWallet: IWallet = {
3939
address: walletAddress,
4040
points: holdings,
41-
verified: false, // todo when we have XUMM integration
41+
verified: false,
4242
};
4343

4444
const newUser: IBotUser = {

0 commit comments

Comments
 (0)