Skip to content

Commit c503c3d

Browse files
committed
inboxId and address distinction
1 parent fa3ca6c commit c503c3d

9 files changed

+163
-190
lines changed

integrations/coinbase-langchain/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"@types/node": "^22.13.0",
3434
"dotenv": "^16.4.7",
3535
"tsx": "^4.19.2",
36-
"typescript": "^5.7.3",
37-
"typescript-eslint": "^8.22.0"
36+
"typescript": "^5.7.3"
3837
}
3938
}

integrations/coinbase-langchain/src/cdp.ts

+81-131
Original file line numberDiff line numberDiff line change
@@ -5,84 +5,66 @@ import {
55
type Transfer,
66
type WalletData,
77
} from "@coinbase/coinbase-sdk";
8-
import { isAddress, keccak256, toBytes, toHex } from "viem";
8+
import { isAddress } from "viem";
99
import { getWalletData, saveWalletData } from "./storage";
1010

11-
// Warn about optional variables
12-
if (!process.env.NETWORK_ID) {
13-
console.warn("Warning: NETWORK_ID not set, defaulting to base-mainnet");
14-
}
15-
11+
const coinbaseApiKeyName = process.env.CDP_API_KEY_NAME;
12+
let coinbaseApiKeyPrivateKey = process.env.CDP_API_KEY_PRIVATE_KEY;
1613
const networkId = process.env.NETWORK_ID ?? "base-sepolia";
1714

15+
if (!coinbaseApiKeyName || !coinbaseApiKeyPrivateKey || !networkId) {
16+
console.error(
17+
"Either networkId, CDP_API_KEY_NAME or CDP_API_KEY_PRIVATE_KEY must be set",
18+
);
19+
process.exit(1);
20+
}
21+
1822
class WalletStorage {
19-
async get(key: string): Promise<string | undefined> {
23+
async get(inboxId: string): Promise<string | undefined> {
2024
try {
21-
const data = await getWalletData(key, networkId);
25+
const data = await getWalletData(inboxId, networkId);
2226
return data ?? undefined;
2327
} catch (error: unknown) {
2428
const errorMessage =
2529
error instanceof Error ? error.message : String(error);
26-
console.error(`Error getting wallet data for ${key}:`, errorMessage);
30+
console.error(`Error getting wallet data for ${inboxId}:`, errorMessage);
2731
return undefined;
2832
}
2933
}
3034

31-
async set(key: string, value: string): Promise<void> {
35+
async set(inboxId: string, value: string): Promise<void> {
3236
try {
33-
await saveWalletData(key, value, networkId);
37+
await saveWalletData(inboxId, value, networkId);
3438
} catch (error: unknown) {
3539
const errorMessage =
3640
error instanceof Error ? error.message : String(error);
37-
console.error(`Error saving wallet data for ${key}:`, errorMessage);
41+
console.error(`Error saving wallet data for ${inboxId}:`, errorMessage);
3842
}
3943
}
4044

41-
async del(key: string): Promise<void> {
45+
async del(inboxId: string): Promise<void> {
4246
try {
43-
await saveWalletData(key, "", networkId);
47+
await saveWalletData(inboxId, "", networkId);
4448
} catch (error: unknown) {
4549
const errorMessage =
4650
error instanceof Error ? error.message : String(error);
47-
console.error(`Error deleting wallet data for ${key}:`, errorMessage);
51+
console.error(`Error deleting wallet data for ${inboxId}:`, errorMessage);
4852
}
4953
}
5054
}
5155

5256
// Initialize Coinbase SDK
5357
function initializeCoinbaseSDK(): boolean {
54-
const coinbaseApiKeyName =
55-
process.env.COINBASE_API_KEY_NAME || process.env.CDP_API_KEY_NAME;
56-
let coinbaseApiKeyPrivateKey =
57-
process.env.COINBASE_API_KEY_PRIVATE_KEY ||
58-
process.env.CDP_API_KEY_PRIVATE_KEY;
5958
// Replace \\n with actual newlines if present in the private key
6059
if (coinbaseApiKeyPrivateKey) {
6160
coinbaseApiKeyPrivateKey = coinbaseApiKeyPrivateKey.replace(/\\n/g, "\n");
6261
}
63-
64-
console.log(
65-
"coinbaseApiKeyName:",
66-
coinbaseApiKeyName ? "Defined" : "Undefined",
67-
);
68-
console.log(
69-
"coinbaseApiKeyPrivateKey:",
70-
coinbaseApiKeyPrivateKey ? "Defined" : "Undefined",
71-
);
72-
console.log("networkId:", networkId ? "Defined" : "Undefined");
73-
if (!coinbaseApiKeyName || !coinbaseApiKeyPrivateKey) {
74-
console.error(
75-
"Either COINBASE_API_KEY_NAME/COINBASE_API_KEY_PRIVATE_KEY or CDP_API_KEY_NAME/CDP_API_KEY_PRIVATE_KEY must be set",
76-
);
77-
return false;
78-
}
79-
8062
try {
8163
Coinbase.configure({
82-
apiKeyName: coinbaseApiKeyName,
83-
privateKey: coinbaseApiKeyPrivateKey,
64+
apiKeyName: coinbaseApiKeyName as string,
65+
privateKey: coinbaseApiKeyPrivateKey as string,
8466
});
85-
console.log("Coinbase SDK initialized successfully");
67+
console.log("Coinbase SDK initialized successfully, network:", networkId);
8668
return true;
8769
} catch (error: unknown) {
8870
const errorMessage = error instanceof Error ? error.message : String(error);
@@ -91,77 +73,41 @@ function initializeCoinbaseSDK(): boolean {
9173
}
9274
}
9375

94-
// Define wallet information structure
95-
interface WalletInfo {
96-
data: WalletData;
97-
agent_address: string;
98-
address: string;
99-
key: string;
100-
}
101-
10276
// Agent wallet data
10377
export type AgentWalletData = {
10478
id: string;
10579
wallet: Wallet;
106-
address: string;
80+
data: WalletData;
81+
human_address: string;
10782
agent_address: string;
10883
blockchain?: string;
10984
state?: string;
110-
key: string;
85+
inboxId: string;
11186
};
11287

11388
// Wallet service class based on cointoss implementation
11489
export class WalletService {
11590
private walletStorage: WalletStorage;
116-
private cdpEncryptionKey: string;
117-
private senderAddress: string;
91+
private humanAddress: string;
92+
private inboxId: string;
11893
private sdkInitialized: boolean;
11994

120-
constructor(sender: string) {
95+
constructor(inboxId: string, address: string) {
12196
this.sdkInitialized = initializeCoinbaseSDK();
12297
this.walletStorage = new WalletStorage();
123-
// Use either KEY or ENCRYPTION_KEY environment variable for local wallet encryption
124-
this.cdpEncryptionKey = (
125-
process.env.KEY ||
126-
process.env.ENCRYPTION_KEY ||
127-
""
128-
).toLowerCase();
129-
this.senderAddress = sender.toLowerCase();
130-
console.log("WalletService initialized with sender", this.senderAddress);
131-
}
132-
133-
encrypt(data: unknown): string {
134-
let stringData = "";
135-
if (typeof data === "string") {
136-
stringData = data.toLowerCase();
137-
} else {
138-
stringData = JSON.stringify(data);
139-
}
140-
141-
const key = keccak256(toHex(this.cdpEncryptionKey));
142-
// Simple XOR encryption with the key
143-
const encrypted = Buffer.from(stringData).map(
144-
(byte, i) => byte ^ parseInt(key.slice(2 + (i % 64), 4 + (i % 64)), 16),
145-
);
146-
return toHex(encrypted).toLowerCase();
147-
}
148-
149-
decrypt(data: string): WalletInfo {
150-
if (typeof data === "string") {
151-
data = data.toLowerCase();
152-
}
153-
const key = keccak256(toHex(this.cdpEncryptionKey));
154-
const encrypted = toBytes(data);
155-
const decrypted = encrypted.map(
156-
(byte, i) => byte ^ parseInt(key.slice(2 + (i % 64), 4 + (i % 64)), 16),
98+
this.humanAddress = address;
99+
this.inboxId = inboxId;
100+
console.log(
101+
"WalletService initialized with sender address",
102+
this.humanAddress,
103+
"and inboxId",
104+
this.inboxId,
157105
);
158-
return JSON.parse(Buffer.from(decrypted).toString()) as WalletInfo;
159106
}
160107

161-
async createWallet(key: string): Promise<AgentWalletData> {
108+
async createWallet(): Promise<AgentWalletData> {
162109
try {
163-
key = key.toLowerCase();
164-
console.log(`Creating new wallet for key ${key}...`);
110+
console.log(`Creating new wallet for key ${this.inboxId}...`);
165111

166112
// Initialize SDK if not already done
167113
if (!this.sdkInitialized) {
@@ -190,30 +136,35 @@ export class WalletService {
190136

191137
// Make the wallet address visible in the logs for funding
192138
console.log("-----------------------------------------------------");
193-
console.log(`NEW WALLET CREATED FOR USER: ${key}`);
139+
console.log(`NEW WALLET CREATED FOR USER: ${this.humanAddress}`);
194140
console.log(`WALLET ADDRESS: ${walletAddress}`);
195141
console.log(`NETWORK: ${networkId}`);
196142
console.log(`SEND FUNDS TO THIS ADDRESS TO TEST: ${walletAddress}`);
197143
console.log("-----------------------------------------------------");
198144

199-
const walletInfo: WalletInfo = {
200-
data,
145+
const walletInfo: AgentWalletData = {
146+
id: walletAddress,
147+
wallet: wallet,
148+
data: data,
149+
human_address: this.humanAddress,
201150
agent_address: walletAddress,
202-
address: this.senderAddress,
203-
key,
151+
inboxId: this.inboxId,
204152
};
205153

206154
console.log("Saving wallet data to storage...");
207-
await this.walletStorage.set(this.encrypt(key), this.encrypt(walletInfo));
208-
209-
console.log("Wallet created and saved successfully");
210-
return {
211-
id: walletAddress,
212-
wallet: wallet,
213-
address: this.senderAddress,
155+
const walletInfoToStore = {
156+
data: data,
157+
human_address: this.humanAddress,
214158
agent_address: walletAddress,
215-
key: key,
159+
inboxId: this.inboxId,
216160
};
161+
await this.walletStorage.set(
162+
this.inboxId,
163+
JSON.stringify(walletInfoToStore),
164+
);
165+
166+
console.log("Wallet created and saved successfully");
167+
return walletInfo;
217168
} catch (error: unknown) {
218169
console.error("Failed to create wallet:", error);
219170

@@ -227,21 +178,19 @@ export class WalletService {
227178
}
228179

229180
async getWallet(
230-
key: string,
181+
inboxId: string,
231182
createIfNotFound: boolean = true,
232183
): Promise<AgentWalletData | undefined> {
233-
console.log("Getting wallet for:", key);
234-
key = key.toLowerCase();
235-
const encryptedKey = this.encrypt(key);
236-
const walletData = await this.walletStorage.get(encryptedKey);
184+
console.log("Getting wallet for:", inboxId);
185+
const walletData = await this.walletStorage.get(inboxId);
237186

238187
// If no wallet exists, create one
239188
if (!walletData) {
240-
console.log("No wallet found for", key);
189+
console.log("No wallet found for", inboxId);
241190
if (createIfNotFound) {
242191
console.log("Creating new wallet as none was found");
243192
try {
244-
const wallet = await this.createWallet(key);
193+
const wallet = await this.createWallet();
245194
console.log("Successfully created new wallet, returning wallet data");
246195
return wallet;
247196
} catch (error: unknown) {
@@ -256,10 +205,10 @@ export class WalletService {
256205

257206
try {
258207
console.log("Found existing wallet data, decrypting...");
259-
const decrypted = this.decrypt(walletData);
208+
const walletInfo = JSON.parse(walletData) as AgentWalletData;
260209

261210
console.log("Importing wallet from stored data...");
262-
const importedWallet = await Wallet.import(decrypted.data).catch(
211+
const importedWallet = await Wallet.import(walletInfo.data).catch(
263212
(err: unknown) => {
264213
const errorMessage = err instanceof Error ? err.message : String(err);
265214
console.error("Error importing wallet:", errorMessage);
@@ -271,9 +220,10 @@ export class WalletService {
271220
return {
272221
id: importedWallet.getId() ?? "",
273222
wallet: importedWallet,
274-
agent_address: decrypted.agent_address,
275-
address: decrypted.address,
276-
key: decrypted.key,
223+
data: walletInfo.data,
224+
human_address: walletInfo.human_address,
225+
agent_address: walletInfo.agent_address,
226+
inboxId: walletInfo.inboxId,
277227
};
278228
} catch (error: unknown) {
279229
const errorMessage =
@@ -283,27 +233,26 @@ export class WalletService {
283233
// If we failed to import, but have wallet data, attempt to recreate
284234
if (createIfNotFound) {
285235
console.log("Attempting to recreate wallet after import failure");
286-
return this.createWallet(key);
236+
return this.createWallet();
287237
}
288238

289239
throw new Error("Invalid wallet access");
290240
}
291241
}
292242

293243
async checkBalance(
294-
humanAddress: string,
244+
inboxId: string,
295245
): Promise<{ address: string | undefined; balance: number }> {
296-
humanAddress = humanAddress.toLowerCase();
297-
console.log(`⚖️ Checking balance for user: ${humanAddress}...`);
246+
console.log(`⚖️ Checking balance for user with inboxId: ${inboxId}...`);
298247

299-
const walletData = await this.getWallet(humanAddress);
248+
const walletData = await this.getWallet(inboxId);
300249
if (!walletData) {
301-
console.log(`❌ No wallet found for ${humanAddress}`);
250+
console.log(`❌ No wallet found for user with inboxId: ${inboxId}`);
302251
return { address: undefined, balance: 0 };
303252
}
304253

305254
console.log(
306-
`✅ Retrieved wallet with address: ${walletData.agent_address} for user: ${humanAddress}`,
255+
`✅ Retrieved wallet with address: ${walletData.agent_address} for user with inboxId: ${inboxId}`,
307256
);
308257

309258
try {
@@ -312,7 +261,7 @@ export class WalletService {
312261
);
313262
const balance = await walletData.wallet.getBalance(Coinbase.assets.Usdc);
314263
console.log(
315-
`💵 USDC Balance for ${humanAddress}: ${Number(balance)} USDC`,
264+
`💵 USDC Balance for user with inboxId: ${inboxId}: ${Number(balance)} USDC`,
316265
);
317266
console.log(Coinbase.assets.Usdc);
318267

@@ -324,7 +273,7 @@ export class WalletService {
324273
const errorMessage =
325274
error instanceof Error ? error.message : String(error);
326275
console.error(
327-
`❌ Error getting balance for ${humanAddress}:`,
276+
`❌ Error getting balance for user with inboxId: ${inboxId}:`,
328277
errorMessage,
329278
);
330279
return {
@@ -335,23 +284,24 @@ export class WalletService {
335284
}
336285

337286
async transfer(
338-
fromAddress: string,
287+
inboxId: string,
288+
humanAddress: string,
339289
toAddress: string,
340290
amount: number,
341291
): Promise<Transfer | undefined> {
342-
fromAddress = fromAddress.toLowerCase();
292+
humanAddress = humanAddress.toLowerCase();
343293
toAddress = toAddress.toLowerCase();
344294

345295
console.log("📤 TRANSFER INITIATED");
346296
console.log(`💸 Amount: ${amount} USDC`);
347-
console.log(`🔍 From user: ${fromAddress}`);
297+
console.log(`🔍 From user: ${humanAddress}`);
348298
console.log(`🔍 To: ${toAddress}`);
349299

350300
// Get the source wallet
351-
console.log(`🔑 Retrieving source wallet for user: ${fromAddress}...`);
352-
const from = await this.getWallet(fromAddress);
301+
console.log(`🔑 Retrieving source wallet for user: ${humanAddress}...`);
302+
const from = await this.getWallet(inboxId);
353303
if (!from) {
354-
console.error(`❌ No wallet found for sender: ${fromAddress}`);
304+
console.error(`❌ No wallet found for sender: ${humanAddress}`);
355305
return undefined;
356306
}
357307
console.log(`✅ Source wallet found: ${from.agent_address}`);

0 commit comments

Comments
 (0)