Discord
You can associate your Discord account with your DEMOS address using one of two methods:
- OAuth Flow (Recommended) - Seamless authentication through the Key Server OAuth system
- Message-based Verification - Manual proof posting in a Discord channel
Method 1: OAuth Flow (Recommended)
The OAuth flow provides a seamless user experience by authenticating through the Key Server, which handles the Discord OAuth process and provides cryptographic attestation.
For detailed information about the Key Server OAuth system, including attestation verification and error handling, see the Key Server OAuth documentation.
1. Verify Discord Account Ownership
Use the KeyServerClient to verify the user owns a Discord account:
import { Demos } from "@kynesyslabs/demosdk/websdk";
import { KeyServerClient } from "@kynesyslabs/demosdk/keyserver";
const demos = new Demos();
await demos.connect("https://node2.demos.sh");
const client = new KeyServerClient({
endpoint: "https://node2.demos.sh",
nodePubKey: "node_public_key_hex",
});
// Complete OAuth verification with optional wallet binding
const result = await client.verifyOAuth("discord", {
onAuthUrl: (url) => {
// Open Discord authorization in a popup
window.open(url, "discord-oauth", "width=600,height=700");
},
onPoll: (attempt, status) => {
console.log(`Verification status: ${status}`);
},
timeout: 300000, // 5 minutes
// Optional: Bind wallet address to this verification for sybil resistance
walletBinding: async (state) => {
const message = `demos-oauth-bind:${state}`;
const signature = await wallet.signMessage(message);
return { address: wallet.address, signature, signatureType: "evm" };
},
});
console.log("Verified user:", result.user.username);
console.log("Provider ID:", result.user.providerId);
2. Submit Identity Transaction
After successful verification, use the attestation to create an identity transaction:
import { Identities } from "@kynesyslabs/demosdk/abstraction";
await demos.connectWallet(mnemonic);
const identities = new Identities();
const validityData = await identities.addDiscordIdentityFromOAuth(
demos,
{
attestation: {
provider: "discord",
userId: result.user.providerId,
username: result.user.username,
timestamp: result.user.verifiedAt,
nodePublicKey: result.attestation.metadata.nodePubKey
},
signature: result.attestation.signature.data,
signatureType: "ed25519"
}
);
if (validityData.result === 200) {
const res = await demos.broadcast(validityData);
console.log(res);
}
3. Verify Attestation (Optional)
You can cryptographically verify the attestation before submitting:
import { verifyOAuthAttestation } from "@kynesyslabs/demosdk/keyserver";
const verification = verifyOAuthAttestation(result, KNOWN_KEY_SERVER_PUBKEY);
if (!verification.valid) {
throw new Error(`Invalid attestation: ${verification.reason}`);
}
The OAuth attestation is cryptographically signed by the Key Server, ensuring the identity verification is authentic. See Attestation Verification for details.
Use Wallet Binding to cryptographically link the OAuth identity to a specific wallet address. This provides sybil resistance by proving the user owns both the social account and the wallet.
Method 2: Message-based Verification
This method requires manually posting a cryptographic proof in a Discord channel where the DEMOS bot has access.
1. Connect your wallet
import { Demos } from "@kynesyslabs/demosdk/websdk"
import { Identities } from "@kynesyslabs/demosdk/abstraction";
// the DEMOS rpc
const rpc = "https://node2.demos.sh"
const demos = new Demos();
await demos.connect(rpc);
await demos.connectWallet(mnemonic);
2. Generate the Proof Payload
To link your Discord account to your DEMOS address, you need to post a message containing a proof in a Discord channel. The proof is a string that contains a message, a signature and your public key.
You can generate a proof as shown below:
const identities = new Identities();
const proofPayload = await identities.createWeb2ProofPayload(demos)
console.log("Post this in Discord:", proofPayload)
The proof looks like this:
demos:dw2p:ed25519:e9dd684a031e142ce312b695275b226ab8824f2fd3674db52f28be6c3e9fe027f88a8a9509563....
Post this proof as a message in a Discord server where the DEMOS verification bot has access.
The Discord message must be publicly accessible by the DEMOS network bot. Make sure you post in a channel where the bot can read messages.
3. Send an Identity request
After posting the proof message, copy the Discord message URL and use it to create an identity transaction as shown below:
To get the message URL in Discord:
- Right-click on your message
- Select “Copy Message Link”
The URL format should look like: https://discord.com/channels/{guildId}/{channelId}/{messageId}
const proof = "https://discord.com/channels/123456789/987654321/111222333444"
const validityData = await identities.addDiscordIdentity(demos, proof)
console.log("validity data: ", validityData)
if (validityData.result == 200){
const res = await demos.broadcast(validityData)
console.log(res)
}
A successful transaction response should look like this:
{
"result": 200,
"response": {
"message": "Verified discord proof. Transaction applied."
},
"require_reply": false,
"extra": {
"confirmationBlock": 15
}
}
Getting linked web2 accounts
After the confirmation block has been forged, you can retrieve all your linked accounts as shown:
const web2Ids = await identities.getWeb2Identities()
The response should look like this:
{
"result": 200,
"response": {
"discord": [
{
"proof": "https://discord.com/channels/123456789/987654321/111222333444",
"username": "your_discord_username",
"proofHash": "a1b2c3d4e5f6..."
}
]
},
"require_reply": false,
"extra": null
}
Removing Discord identity
You can create a transaction to remove your linked Discord account as shown:
const payload = {
context: "discord",
username: "your_discord_username"
}
const validityData = await identities.removeWeb2Identity(demos, payload);
if (validityData.result == 200) {
const res = await demos.broadcast(validityData);
console.log(res);
}
A successful transaction response should look like this:
{
"result": 200,
"response": {
"message": "Identity removed. Transaction applied."
},
"require_reply": false,
"extra": {
"confirmationBlock": 20
}
}
The following Discord URL formats are supported for message-based verification:
- Standard message URL:
https://discord.com/channels/{guildId}/{channelId}/{messageId}
- PTB (Public Test Build):
https://ptb.discord.com/channels/{guildId}/{channelId}/{messageId}
- Canary:
https://canary.discord.com/channels/{guildId}/{channelId}/{messageId}
- Legacy domain:
https://discordapp.com/channels/{guildId}/{channelId}/{messageId}
Comparison of Methods
| Feature | OAuth Flow | Message-based |
|---|
| User Experience | Seamless, one-click | Manual message posting |
| Cryptographic Attestation | DAHR attestation with signature | Proof in message |
| Bot Requirement | Not required | Bot must be in server |
| Best For | Production apps | Development/testing |