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

[dnm] rm-keypair #114

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Dialect is a smart messaging protocol for dapp notifications and wallet-to-wallet messaging on the Solana Blockchain.

Dialect works by decorating on-chain resources, or sets of resources, with publish-subscribe (pub-sub) messaging capabilities. This is accomplished by creating a PDA whose seeds are the (lexically sorted) resources' public keys. Each pub-sub messaging PDA is called a _dialect_.

Dialect `v0` currently supports one-to-one messaging between wallets, which powers both dapp notifications as well as user-to-user chat. Future versions of Dialect will also support one-to-many and many-to-many messaging.

This repository contains both the Dialect rust programs (protocol), in Anchor, as well as a typescript client, published to npm as `@dialectlabs/web3`.
Expand Down
71 changes: 33 additions & 38 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as anchor from '@project-serum/anchor';
import { EventParser } from '@project-serum/anchor';
import { Wallet } from '@project-serum/anchor/src/provider';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import { Connection, PublicKey } from '@solana/web3.js';

import { sleep, waitForFinality, Wallet_ } from '../utils';
import { ENCRYPTION_OVERHEAD_BYTES } from '../utils/ecdh-encryption';
Expand Down Expand Up @@ -118,37 +118,37 @@ export async function getMetadataProgramAddress(
// TODO: Simplify this function further now that we're no longer decrypting the device token.
export async function getMetadata(
program: anchor.Program,
user: PublicKey | anchor.web3.Keypair,
otherParty?: PublicKey | anchor.web3.Keypair | null,
user: PublicKey | Wallet,
otherParty?: PublicKey | Wallet | null,
): Promise<Metadata> {
let shouldDecrypt = false;
let userIsKeypair = false;
let otherPartyIsKeypair = false;
let userIsWallet = false;
let otherPartyIsWallet = false;

try {
// assume user is pubkey
new anchor.web3.PublicKey(user.toString());
} catch {
// user is keypair
userIsKeypair = true;
// user is wallet
userIsWallet = true;
}

try {
// assume otherParty is pubkey
new anchor.web3.PublicKey(otherParty?.toString() || '');
} catch {
// otherParty is keypair or null
otherPartyIsKeypair = (otherParty && true) || false;
// otherParty is wallet or null
otherPartyIsWallet = (otherParty && true) || false;
}

if (otherParty && (userIsKeypair || otherPartyIsKeypair)) {
if (otherParty && (userIsWallet || otherPartyIsWallet)) {
// cases 3 - 5
shouldDecrypt = true;
}

const [metadataAddress] = await getMetadataProgramAddress(
program,
userIsKeypair ? (user as Keypair).publicKey : (user as PublicKey),
userIsWallet ? (user as Wallet).publicKey : (user as PublicKey),
);
const metadata = await program.account.metadataAccount.fetch(metadataAddress);

Expand All @@ -162,51 +162,50 @@ export async function getMetadata(

export async function createMetadata(
program: anchor.Program,
user: anchor.web3.Keypair | Wallet,
): Promise<Metadata> {
const wallet = program.provider.wallet;
const publicKey = wallet.publicKey;
const [metadataAddress, metadataNonce] = await getMetadataProgramAddress(
program,
user.publicKey,
publicKey,
);
const tx = await program.rpc.createMetadata(new anchor.BN(metadataNonce), {
accounts: {
user: user.publicKey,
user: publicKey,
metadata: metadataAddress,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: 'secretKey' in user ? [user] : [],
});
await waitForFinality(program, tx);
return await getMetadata(program, user.publicKey);
return await getMetadata(program, publicKey);
}

export async function deleteMetadata(
program: anchor.Program,
user: anchor.web3.Keypair | Wallet,
): Promise<void> {
export async function deleteMetadata(program: anchor.Program): Promise<void> {
const wallet = program.provider.wallet;
const publicKey = wallet.publicKey;
const [metadataAddress, metadataNonce] = await getMetadataProgramAddress(
program,
user.publicKey,
publicKey,
);
await program.rpc.closeMetadata(new anchor.BN(metadataNonce), {
accounts: {
user: user.publicKey,
user: publicKey,
metadata: metadataAddress,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: 'secretKey' in user ? [user] : [],
});
}

export async function subscribeUser(
program: anchor.Program,
dialect: DialectAccount,
user: PublicKey,
signer: Keypair,
): Promise<Metadata> {
const [publicKey, nonce] = await getDialectProgramAddress(
const wallet = program.provider.wallet;
const publicKey = wallet.publicKey;
const [dialectPublicKey, nonce] = await getDialectProgramAddress(
program,
dialect.dialect.members,
);
Expand All @@ -219,14 +218,13 @@ export async function subscribeUser(
new anchor.BN(metadataNonce),
{
accounts: {
dialect: publicKey,
signer: signer.publicKey,
dialect: dialectPublicKey,
signer: publicKey,
user: user,
metadata,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: [signer],
},
);
await waitForFinality(program, tx);
Expand Down Expand Up @@ -320,10 +318,10 @@ export async function getDialect(

export async function getDialects(
program: anchor.Program,
user: anchor.web3.Keypair | Wallet,
user: PublicKey | Wallet, // TODO: why we need wallet here?
encryptionProps?: EncryptionProps,
): Promise<DialectAccount[]> {
const metadata = await getMetadata(program, user.publicKey);
const metadata = await getMetadata(program, user);
const enabledSubscriptions = metadata.subscriptions.filter(
(it) => it.enabled,
);
Expand Down Expand Up @@ -394,11 +392,11 @@ export async function findDialects(

export async function createDialect(
program: anchor.Program,
owner: anchor.web3.Keypair | Wallet,
members: Member[],
encrypted = false,
encryptionProps?: EncryptionProps,
): Promise<DialectAccount> {
const owner = program.provider.wallet;
const sortedMembers = members.sort((a, b) =>
a.publicKey.toBuffer().compare(b.publicKey.toBuffer()),
);
Expand All @@ -423,7 +421,6 @@ export async function createDialect(
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: 'secretKey' in owner ? [owner] : [],
},
);
await waitForFinality(program, tx);
Expand All @@ -433,20 +430,19 @@ export async function createDialect(
export async function deleteDialect(
program: anchor.Program,
{ dialect }: DialectAccount,
owner: anchor.web3.Keypair | Wallet,
): Promise<void> {
const wallet = program.provider.wallet;
const [dialectPublicKey, nonce] = await getDialectProgramAddress(
program,
dialect.members,
);
await program.rpc.closeDialect(new anchor.BN(nonce), {
accounts: {
dialect: dialectPublicKey,
owner: owner.publicKey,
owner: wallet.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: 'secretKey' in owner ? [owner] : [],
});
}

Expand All @@ -466,7 +462,6 @@ Messages
export async function sendMessage(
program: anchor.Program,
{ dialect, publicKey }: DialectAccount,
sender: anchor.web3.Keypair | Wallet,
text: string,
encryptionProps?: EncryptionProps,
): Promise<Message> {
Expand All @@ -482,19 +477,19 @@ export async function sendMessage(
encryptionProps,
);
const serializedText = textSerde.serialize(text);
const wallet = program.provider.wallet;
await program.rpc.sendMessage(
new anchor.BN(nonce),
Buffer.from(serializedText),
{
accounts: {
dialect: dialectPublicKey,
sender: sender ? sender.publicKey : program.provider.wallet.publicKey,
sender: wallet.publicKey,
member0: dialect.members[0].publicKey,
member1: dialect.members[1].publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
signers: sender && 'secretKey' in sender ? [sender] : [],
},
);
const d = await getDialect(program, publicKey, encryptionProps);
Expand Down
Loading