# NFT-Twitter
# Taskslist
- NFT-Webapp Single-Page UI (Simonas)
- List Tweets (all Tweets, no filter)
- List NFTs
- Select active NFT
- Tweet with (active) NFT
- New: "Send private Message" to NFT
- New: "Receive private Message" on Agent
- Agent/API:
- Expose VCs: /dataStoreGetVerifiableCredential :heavy_check_mark:
- Expose Msg Endpoint to receive credentials :heavy_check_mark:
- DID:NFT resolver must be working Server-Side :heavy_check_mark:
- "Find/Read all NFTs" for Ethereum Address (via opensea) :heavy_check_mark:
- MessageHandler-Chain to verif and unwrap Metamask-signed Messages (Mircea, Oliver, Martin) :heavy_check_mark:
- No JSON-LD dependency. Special MM-JWT credential & Message Handler. @Martin @ @Oliver
- Expose Opensea API calls in own backend with Opensea API Key :exclamation:
- Metamask / Veramo Integration
- KMS-Veramo Integration :heavy_check_mark:
- MemoryDIDStore :heavy_check_mark:
- MemoryKeyStore :heavy_check_mark:
- Web3KeyManagementSystem (Sign) :heavy_check_mark:
- Metamask cannot sign our Secp256k1 JWT representation
- No JSON-LD dependency. Special MM-JWT credential & Message Handler. @Mircea
- MetaMask Credential Signing with EIP-712 support. (Simonas): (may, for FRI) :heavy_check_mark:
- Architecture Diagram (Oliver) :heavy_check_mark:
- Demo Flow Design and Presentation (Rouven, Martin) :heavy_check_mark:
- Demo transfer of NFT? (not part of friday demo)
- Where does Veramo come in?
- Where to go from here?
- Break it down to "base components"
- Central Hosted Accumulator (did:web agent)
- Metamask KMS Integration
- DID:NFT resolver
- Credential Proof Format
- :hammer: Migrate solution from JWT to JSON-LD Credentials (Martin) - Maybe in context with Metamask-Sig
- "Web3-Veramo-Kit" should be separate from agent explorer codebase. - Out of scope for friday's demo
# Outcome / Learning
- Backend / Frontend Code Sharing within Projects like Pulsar
- Wrap outcome into dApp Library for web3 frontend signing. (Preconfigured Web3 provider that is automatically provided to KeyManager, DIDManager and Messaging) -> Greg, Simonas
- Web3 / Metamask Handling (e.g. Connect, Disconnect) is out-of-scope of Veramo.
- "Profile Credential" for name and profile pic for any DID.
- Prepare Deployment Infrastructure to dynamically handle bigger loads (e.g. provide Credit Card information)
# Discussion Points
- How to resolve messaging endpoints for `did:nfts?`
- Martin: Is that relevant for MVP?
- Client -> Twitter NFT Agent Hard-coded for demo?
- Twitter NFT Agent -> Client: No communication
- did:ethr as controller of did:nft:
- ERC721 specifies an ethereum address as owner, not a did:ethr. Key rotations in did:ethr are not represented in ERC721.
- Owner addresses of various NFTs are NOT necessarily DID compliant
- [did:nft](https://github.com/ceramicnetwork/CIP/blob/main/CIPs/CIP-94/CIP-94.md) method by Ceramic
- Relies heavily on chain-agnostic CAIP specs.
- Faces the same problem as stated above. Existing NFTs do not present owner as DIDs
- Mircea: We would have a different view of a did:nft method. On Friday start conversation with Ceramic.
- Serto: https://serto.medium.com/verifiable-authorship-for-the-150-million-nft-art-market-8a7affe90186
- "Web3-Veramo-Kit" should be separate from agent explorer codebase.
- EIP-1056 on Matic: not prioritized
# Resources
- [Olivers Whimsical](https://whimsical.com/nft-demo-J1vEefJnSqp4XVCU91g95t)
- Original Design Notes on [Whimsical](https://whimsical.com/twitter-for-nfts-TLJBMoYBGaKLXfgK7Vx1r1)
# Grooming Meeting 3/15/2021
## Agenda:
- Wednesday Meeting: What to show:
- Rouven: Updated presentation / messaging
- Demos?
- DID:NFT Method
- Veramo Client-side Metamask demo (NFT-Twitter)
- DID-Chat (NFT-Chat): A->B hosted on Server C
## Protocol
- Internal Consensys Meeting on 3/17 with Consensys Leadership Team
- Extended Demo Ideas:
- Simonas: Include Messaging Part in Same Demo.
- Include "private Messaging" in Twitter NFT Demo
- Be able to send messages to the messaging endpoint of the did:nft
- Every client would need an endpoint to receive private messages.
- Public "Messaging Instance" of Veramo: How would that work?
- Message must be encrypted for receipient
- Message must be able to integrity checked on server side
- Retrieving (encrypted) messages should only be possible for receipient.
- For Wednesday Demo:
- Restrict to Demo to send private messages to personal endpoints.
- Challenges: Where does the endpoint information live?
- Rouven: Use different Skins for NFT-Twitter and Personal Message portal, so that audience understand the different
- Simonas: Contact Form for NFTs?
- Simonas: VC can be NFTs that are not in the Blockchain yet.
YOU own -> VCs
YOU own -> NFTs
connection via (YOU). I don't see UC VC->NFT
- Should VC (like Ethr) have a possibility to point to a on-chain transfer?
- CredentialStatus with "Transfer" support. e.g. credentialSubject changed from DID1 to DID2.
- Assigned new Tasks until Wednesday
# Metamask Credential EIP712 Example:
```
const credential = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3id.org/veramolabs/socialmedia/context/v1"
],
"type": [
"VerifiableCredential",
"VerifableSocialMediaPosting"
],
"id": "https://example.org/post/1234",
"issuer": "did:example:aadsfewfweasdfsfad",
"issuanceDate": "2010-01-01T19:23:24Z",
"credentialSubject": {
// might contain reply tweet URL
"id": "https://example.org/post/1234",
"type": "SocialMediaPosting",
"author": {
"id": "did:nft:ebfeb1f712ebc6f1c276e12ec21",
"type": "Person",
"thumbnail": "https://google.com",
"image": "https://google.com",
"name": "cryptopunk"
},
"headline": "punks are aliens",
"articleBody": "waffles for zoomers"
},
"credentialSchema": {
"id": "https://www.w3id.org/veramolabs/socialmedia/context/v1/eip712.json",
"type": "Eip712SchemaValidator2021"
}
};
// TODO: normally one should get eip712 schema from credentialSchema URI
const eip712Schema = {
VerifiableCredential: [
{ name: '@context', type: 'string[]' },
{ name: 'type', type: 'string[]' },
{ name: 'id', type: 'string' },
{ name: 'issuer', type: 'string' },
{ name: 'issuanceDate', type: 'string' },
{ name: 'credentialSubject', type: 'CredentialSubject' },
{ name: 'credentialSchema', type: 'CredentialSchema' }
],
CredentialSchema: [
{ name: 'id', type: 'string' },
{ name: 'type', type: 'string' },
],
CredentialSubject: [
{ name: 'type', type: 'string' },
{ name: 'id', type: 'string' },
{ name: 'headline', type: 'string' },
{ name: 'articleBody', type: 'string' },
{ name: 'author', type: 'Person' }
],
Person: [
{ name: 'type', type: 'string' },
{ name: 'id', type: 'string' },
{ name: 'thumbnail', type: 'string' },
{ name: 'image', type: 'string' },
{ name: 'name', type: 'string' }
]
};
// TODO: normalize credential using JCS
const data = JSON.stringify({
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'salt', type: 'bytes32' },
],
... eip712Schema
},
domain: {
name: 'Sign Tweet',
version: '2',
chainId: 4,
salt: '0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558',
},
primaryType: 'VerifiableCredential',
message: {
... credential
}
});
const signer = walletAddress;
const params = [signer, data];
web3.currentProvider.sendAsync(
{
method: 'eth_signTypedData_v4',
params,
from: signer,
jsonrpc: '2.0',
id: new Date().getTime(),
},
(error, response) => {
if (error) {
return setErrorMsg(error.message);
} else if (response && response.error) {
const errMsg = response.error.message.substring(0, 70).concat('...');
return setErrorMsg(errMsg);
} else {
const result = response && response.result;
const signature = result && result.substring(2);
const r = signature && '0x' + signature.substring(0, 64);
const s = signature && '0x' + signature.substring(64, 128);
const v = signature && parseInt(signature.substring(128, 130), 16);
const signatures = {
signature,
r,
s,
v,
};
setSuccessMsg(`Successfully signed data!! ${signature}`);
setData({ signatures, ...JSON.parse(data) });
}
}
);
};
```
Resulting Proof:
```
"proof": {
"type": "EthereumEip712Signature2021",
"verificationMethod": "did:ethr:0xabc#...",
"proofPurpose": "assertionMethod",
"domain": {
"name": 'Sign Tweet',
"version": '2',
"chainId": 4,
"salt": '0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558',
},
"signature": "a5976468abf6b39242bd892c19047e4f83454f31c073b3d6e87954fbef259e156a3fbe2ae401054e6efaa1097647b2236cd11fdc322680405a1e840614d2ac601c"
}
```