Skip to content

Commit 9d62d0e

Browse files
committed
deploy
1 parent a4046b9 commit 9d62d0e

File tree

5 files changed

+80
-48
lines changed

5 files changed

+80
-48
lines changed

README.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ const members = await group.members();
3838

3939
> To learn more about groups, read the [XMTP documentation](https://docs.xmtp.org).
4040
41+
## Keys
42+
43+
By default, your bot will have a new address every time you start it up. That's ideal. If you have a private key, you can encode it to a hex string and set the KEY environment variable. Your bot will then use this key to connect to the network.
44+
45+
Don't know how to create a private key? Here's how to do it with ethers.js:
46+
4147
## Web inbox
4248

4349
Interact with the XMTP protocol using [xmtp.chat](https://xmtp.chat) the official web inbox for developers using the latest version powered by MLS.
@@ -61,10 +67,16 @@ yarn install
6167
yarn build
6268

6369
# gm example
70+
yarn gm
71+
# or
72+
cd examples
6473
cd gm
6574
yarn dev
6675

67-
# gated grouo
76+
# gated group example
77+
yarn gated
78+
# or
79+
cd examples
6880
cd gated-group
6981
yarn dev
7082
```

examples/gated-group/src/groups.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export async function createGroup(
1010
await client.conversations.sync();
1111
const conversations = client.conversations.list();
1212
console.log("Conversations", conversations.length);
13+
/* If you have the inboxId you can use group.addMembersByInboxId instead*/
1314
const group = await client.conversations.newGroup([
1415
senderAddress,
1516
clientAddress,

examples/gated-group/src/keys.ts

+54-41
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,64 @@
11
import { getRandomValues } from "node:crypto";
22
import * as fs from "node:fs";
33
import path from "path";
4-
import { toHex } from "viem";
5-
6-
export function generateKeys(
7-
walletKey?: string,
8-
encryptionKey?: string,
9-
suffix: string = "",
10-
) {
11-
encryptionKey =
12-
encryptionKey ??
13-
process.env["ENCRYPTION_KEY" + suffix] ??
14-
toHex(getRandomValues(new Uint8Array(32)));
15-
16-
if (!encryptionKey.startsWith("0x")) {
17-
encryptionKey = "0x" + encryptionKey;
18-
}
19-
walletKey =
20-
walletKey ??
21-
process.env["WALLET_KEY" + suffix] ??
22-
toHex(getRandomValues(new Uint8Array(32)));
4+
import { toBytes, toHex } from "viem";
5+
6+
class KeyManager {
7+
private suffix: string;
238

24-
if (!walletKey.startsWith("0x")) {
25-
walletKey = "0x" + walletKey;
9+
constructor(suffix: string = "") {
10+
this.suffix = suffix;
2611
}
27-
return { walletKey, encryptionKey };
28-
}
2912

30-
export function saveKeys(
31-
walletKey: string,
32-
encryptionKey: string,
33-
suffix: string = "",
34-
) {
35-
const envFilePath = path.resolve(process.cwd(), ".env");
36-
const envContent = `\nENCRYPTION_KEY${suffix}=${encryptionKey}\nWALLET_KEY${suffix}=${walletKey}`;
37-
38-
// Read the existing .env file content
39-
let existingEnvContent = "";
40-
if (fs.existsSync(envFilePath)) {
41-
existingEnvContent = fs.readFileSync(envFilePath, "utf8");
13+
generateKeys(
14+
walletKey?: string,
15+
encryptionKey?: string,
16+
): {
17+
walletKey: string;
18+
encryptionKey: string;
19+
encryptionKeyBytes: Uint8Array;
20+
} {
21+
encryptionKey =
22+
encryptionKey ??
23+
process.env["ENCRYPTION_KEY" + this.suffix] ??
24+
toHex(getRandomValues(new Uint8Array(32)));
25+
26+
if (!encryptionKey.startsWith("0x")) {
27+
encryptionKey = "0x" + encryptionKey;
28+
}
29+
const encryptionKeyBytes = new Uint8Array(
30+
toBytes(encryptionKey as `0x${string}`),
31+
);
32+
33+
walletKey =
34+
walletKey ??
35+
process.env["WALLET_KEY" + this.suffix] ??
36+
toHex(getRandomValues(new Uint8Array(32)));
37+
38+
if (!walletKey.startsWith("0x")) {
39+
walletKey = "0x" + walletKey;
40+
}
41+
return { walletKey, encryptionKey, encryptionKeyBytes };
4242
}
4343

44-
// Check if the keys already exist
45-
if (
46-
!existingEnvContent.includes(`ENCRYPTION_KEY${suffix}=`) &&
47-
!existingEnvContent.includes(`WALLET_KEY${suffix}=`)
48-
) {
49-
fs.appendFileSync(envFilePath, envContent);
44+
saveKeys(walletKey: string, encryptionKey: string) {
45+
const envFilePath = path.resolve(process.cwd(), ".env");
46+
const envContent = `\nENCRYPTION_KEY${this.suffix}=${encryptionKey}\nWALLET_KEY${this.suffix}=${walletKey}`;
47+
48+
// Read the existing .env file content
49+
let existingEnvContent = "";
50+
if (fs.existsSync(envFilePath)) {
51+
existingEnvContent = fs.readFileSync(envFilePath, "utf8");
52+
}
53+
54+
// Check if the keys already exist
55+
if (
56+
!existingEnvContent.includes(`ENCRYPTION_KEY${this.suffix}=`) &&
57+
!existingEnvContent.includes(`WALLET_KEY${this.suffix}=`)
58+
) {
59+
fs.appendFileSync(envFilePath, envContent);
60+
}
5061
}
5162
}
63+
64+
export default KeyManager;

examples/gated-group/src/xmtp.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import {
66
type DecodedMessage,
77
} from "@xmtp/node-sdk";
88
import dotenv from "dotenv";
9-
import { toBytes } from "viem";
10-
import { generateKeys, saveKeys } from "./keys.js";
9+
import KeyManager from "./keys.js";
1110
import { createSigner, createUser } from "./viem.js";
1211

1312
dotenv.config();
@@ -25,8 +24,13 @@ export async function createClient({
2524
options?: ClientOptions;
2625
streamMessageCallback?: (message: DecodedMessage) => Promise<void>;
2726
}): Promise<Client> {
28-
const { walletKey: clientWalletKey, encryptionKey: clientEncryptionKey } =
29-
generateKeys(walletKey, encryptionKey, suffix);
27+
const keyManager = new KeyManager(suffix);
28+
29+
const {
30+
walletKey: clientWalletKey,
31+
encryptionKey: clientEncryptionKey,
32+
encryptionKeyBytes: clientEncryptionKeyBytes,
33+
} = keyManager.generateKeys(walletKey, encryptionKey);
3034

3135
const user = createUser(clientWalletKey);
3236

@@ -45,14 +49,14 @@ export async function createClient({
4549

4650
const client = await Client.create(
4751
createSigner(user),
48-
new Uint8Array(toBytes(encryptionKey as `0x${string}`)),
52+
clientEncryptionKeyBytes,
4953
clientConfig,
5054
);
5155

5256
if (streamMessageCallback) {
5357
void streamMessages(streamMessageCallback, client);
5458
}
55-
saveKeys(clientWalletKey, clientEncryptionKey, suffix);
59+
keyManager.saveKeys(clientWalletKey, clientEncryptionKey);
5660
return client;
5761
}
5862

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"examples": "node scripts/examples.js",
1515
"format": "prettier -w .",
1616
"format:check": "prettier -c .",
17+
"gated": "cd examples/gated-group && yarn dev",
18+
"gm": "cd examples/gm && yarn dev",
1719
"lint": "yarn build && eslint .",
1820
"publish": "yarn build && changeset publish",
1921
"test": "FORCE_COLOR=1 turbo run test",

0 commit comments

Comments
 (0)