ETH Shanghai Hackathon: Bounty 1: Create Verifiable Credentials Collab.Land Can Consume
Closed this issue · 2 comments
Prize Title
Create Verifiable Credentials [Collab.Land](http://Collab.Land) Can VC Gate From
Prize Bounty
5000 USDC
Possible introduction to MetaCartel for further funding
Challenge Description
[Collab.Land](http://Collab.Land) is a token gating platform that allows communities to restrict access to private communities based on NFT and Fungible token ownership. Verifiable Credentials (VCs) are a new category of signed off chain messages.
https://en.wikipedia.org/wiki/Verifiable_credentials
[Collab.Land](http://Collab.Land) will soon allow token gating based on 3rd party Verifiable Credentials. Some examples include token gating based on: “Your platforms most active users”, “different skill tiers in your online game as defined by VCs issued to users”, “Web2 memberships that come with VCs”. The possibilities are endless. What matters though is the value creation for your users and the Collab.Land ecosystem.
Your challenge is to generate VCs for users from a new or existing platform and propose how they could be used by a community admin to gate community specific chats or features.
For example, all United Airlines Platinum Members gain access to a VC gated customer support real time chat room... You get the idea.
Following the W3C Verifiable Credentials Standard. This proposal from Nuggets to [Collab.Land](http://Collab.Land) provides many useful links: https://github.com/orgs/abridged/discussions/64
Collab.Lands current VC schema: APPENDIX A
Submission Requirements
- a powerpoint/ google slides - still working on an example to share. these are the current slide titles
- Executive Brief
- Simple Summary
- Abstract
- Motivation
- Specifics
- Opportunity
- User Impact
- a video explaining the proposal under 5 minutes (shows energy and personality)
- A video demoing the code and VC generation in under 5 minutes
Judging Criteria
A successful project will show a compelling use case for issuing VCs for use by Community Admins.
Criteria will include:
Value created for the end user
effort put in by the team/ maturity of POC
Feasibility of becoming a widely used product/ use case
Value add to the [Collab.Land](http://Collab.Land) ecosystem
Compelling story that users can understand
Ability to follow through and take the POC into an MVP and eventually production
Winner Announcement Date
One winner will be chosen from all the submissions and will be announced 1 week after submissions close.
Resources
Teams can ask questions in our Discord here:
https://discord.gg/thmcqDx3ys
Note: real time support is only available for hackathon related questions.
Our FAQ and all other questions should be directed to https://collabland.freshdesk.com/
Refer to the "Consume VCs" bounty for additional information: https://github.com/orgs/abridged/discussions/63
APPENDIX A
//=============================================================================
// Licensed Materials - Property of Abridged, Inc.
// (C) Copyright Abridged, Inc. 2022
//=============================================================================
import {auth} from '@collabland/api-security';
import {debugFactory, generateIdSync} from '@collabland/common';
import {userOnly} from '@collabland/component-authorization';
import {experimental} from '@collabland/component-platform';
import {VeramoService, VERAMO_SERVICE} from '@collabland/component-veramo';
import {BindingScope, inject, injectable} from '@loopback/core';
import {get, oas, post, requestBody} from '@loopback/rest';
import {SecurityBindings} from '@loopback/security';
import {DISCORD_SERVICE} from '../keys';
import type {DiscordService} from '../services/discord.service';
import {getDiscordGuildId} from '../services/discord.service';
import {VC} from '../types';
const debug = debugFactory('collabland:veramo-vc');
export interface UserInfo {
provider?: string;
alias: string;
nickname: string;
name: string;
picture: string;
}
interface UserProfile {
id: string;
verifying: VerifyingRoles[];
}
interface VerifyingRoles {
communityId: string;
roleId: string;
roleName: string;
}
interface DiscordUser {
roles: string[];
avatar: string;
joined_at: string;
user: {
id: string;
username: string;
avatar: string;
discriminator: string;
public_flags: number;
};
}
interface CredentialSubjectData {
id: string;
discordUserId: string;
discordUserName: string; //`${user.username}#${user.discriminator}`,
discordUserAvatar: string; //user.displayAvatarURL({ size: 512 }),
discordGuildId: string; //
discordGuildName: string;
discordGuildAvatar: string; //guild.iconURL({ size: 512 }),
discordRoleId: string;
discordRoleName: string;
description: string;
exp?: number;
}
interface CredentialSubject {
data: CredentialSubjectData | undefined;
error?: string;
}
interface VCResponse {
data: VC[];
error?: string;
}
@experimental()
@auth()
@userOnly()
@injectable({scope: BindingScope.SINGLETON})
export class VeramoController {
constructor(
@inject(VERAMO_SERVICE)
private veramoService: VeramoService,
@inject(DISCORD_SERVICE) private discordService: DiscordService,
) {}
/**
* Get user VCs
*/
@get('/veramo/did/{user}')
@oas.response(200, {
type: 'array',
items: {
type: 'object',
properties: {
chain_id: {type: 'string'},
deployment_address: {type: 'string'},
},
},
})
async getUserVCs(@inject(SecurityBindings.USER) currentUser: UserProfile) {
return [];
}
/**
* Generate VCs for based on roles
*
* @example credentialSubject: {
// user
discordUserId: '412814486332899338',
discordUserName: `Agnes | Collab.Land#2623`,
discordUserAvatar: '14f020ef756a37284281ebbba8ea84a9',
// community
discordGuildId: '903656119656910908',
discordGuildName: 'CL',
discordGuildAvatar: '',
// role
discordRoleId: '907634262461784084',
discordRoleName: 'BKA',
description: 'user Agnes has role BKA in community CL',
},
*
*/
@post('/veramo/identity')
@oas.response(200, {
type: 'object',
})
async generateVc(
@inject(SecurityBindings.USER) currentUser: UserProfile,
@requestBody()
profile: {aeToken: string; verifying: VerifyingRoles[]},
): Promise<VCResponse> {
debug('decode AE token', currentUser);
debug('roles', profile.verifying);
const builtCredentials: CredentialSubject[] = [];
for (const role of profile.verifying) {
const roleInfo = await this.buildRoleInfo(role, currentUser.id);
builtCredentials.push(roleInfo);
}
debug('builtCredentials', builtCredentials);
// TODO: enable other platforms
const userId = `DIS#USER#${currentUser.id}`;
return this.getIdentity(userId, builtCredentials);
}
async getIdentity(userId: string, verifying: CredentialSubject[]) {
return this.getIdentityAndUpdateProfile(userId, verifying);
}
/**
* Veramo agent generates VC
* @param userId
* @param verifying
* @returns
*/
async getIdentityAndUpdateProfile(
userId: string,
verifying: CredentialSubject[],
): Promise<VCResponse> {
const issuer = await this.veramoService.agent.didManagerGetOrCreate({
alias: 'CollabLand',
// provider: userInfo.provider,
});
const vcs: VC[] = [];
for (const credential of verifying) {
if (credential.error) {
return {error: `Invalid community id: ${credential.error}`, data: []};
}
const vc = (await this.veramoService.agent.createVerifiableCredential({
save: true,
proofFormat: 'jwt',
credential: {
id: generateIdSync(),
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential', 'DiscordRole'],
issuer: {id: issuer.did},
issuanceDate: new Date().toISOString(),
credentialSubject: credential.data,
},
})) as unknown as VC;
debug('VC', vc);
vcs.push(vc);
}
return {data: vcs};
}
/**
* Build role information based on the given userId and communityId
* @param role selected role
* @param userId example: 412814486332899338
* @returns
*/
async buildRoleInfo(role: VerifyingRoles, userId: string, ttl = -1) {
const guildId = getDiscordGuildId(role.communityId);
if (!guildId)
return {
error: `Invalid CommunityPk ${role.communityId}`,
data: undefined,
} as CredentialSubject;
const commInfo = await this.discordService.getGuildInfo(guildId);
const userInfo = (await this.discordService.getMemberInfo(
guildId,
userId,
)) as unknown as DiscordUser;
debug('Community info', commInfo);
debug('User info', userInfo);
const data = {
id: userId,
// user
discordUserId: userId,
discordUserName: `${userInfo.user.username}#${userInfo.user.discriminator}`,
discordUserAvatar: userInfo.user.avatar
? this.discordService.cdn.avatar(userId, userInfo.user.avatar)
: '',
// community
discordGuildId: commInfo.id,
discordGuildName: commInfo.name,
discordGuildAvatar: commInfo.icon
? this.discordService.cdn.icon(commInfo.id, commInfo.icon)
: '',
// role
discordRoleId: role.roleId,
discordRoleName: role.roleName,
description: `${userInfo.user.username}#${userInfo.user.discriminator} has role ${role.roleName} in Discord community ${commInfo.name}`,
} as CredentialSubjectData;
if (ttl !== -1) {
data.exp = Date.now() / 1000 + ttl;
}
return {
data,
} as CredentialSubject;
}
}
Issue Status: 1. Open 2. Started 3. Submitted 4. Done
This issue now has a funding of 5000.0 USDC (5000.0 USD @ $1.0/USDC) attached to it.
- If you would like to work on this issue you can 'start work' on the Gitcoin Issue Details page.
- Want to chip in? Add your own contribution here.
- Questions? Checkout Gitcoin Help or the Gitcoin's Discord
- $3,813,783.72 more funded OSS Work available on the Gitcoin Issue Explorer
Issue Status: 1. Open 2. Started 3. Submitted 4. Done
Work has been started.
These users each claimed they can complete the work by 2 hours ago.
Please review their action plans below:
1) fifteen42 has been approved to start work.
DAOU can turn your activities, connections, contributions, etc in DAOs into social capital by Social Oracle Protocol and link your social capital to your soulbound token (SBT).
2) shreyan001 has been approved to start work.
I am currently building a decentralized social network/DAO for political communities where entry is based on on-chain surveys, which can be done only once, I do require guidance for this project off the hackathon.
3) archenetwork has been approved to start work.
Arche is a community oriented space for game enthusiasts for a better Web 3.0 experience. We aims to bring good Web3 games to people and bridge the connection amongst GameFi players to enjoy, earn, create, govern and assembling those to build a better game Metaverse and society.
Learn more on the Gitcoin Issue Details page.