Skip to content

Commit a1e8447

Browse files
authored
Merge pull request #586 from ai16z/shaw/realityspiral/coinbase-fixes
feat: Shaw/realityspiral/coinbase fixes
2 parents 4f773b1 + d18eef5 commit a1e8447

File tree

12 files changed

+1644
-452
lines changed

12 files changed

+1644
-452
lines changed

.env.example

+7-2
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,10 @@ STARKNET_ADDRESS=
9191
STARKNET_PRIVATE_KEY=
9292
STARKNET_RPC_URL=
9393

94-
# Coinbase Commerce
95-
COINBASE_COMMERCE_KEY=
94+
# Coinbase
95+
COINBASE_COMMERCE_KEY= # from coinbase developer portal
96+
COINBASE_API_KEY= # from coinbase developer portal
97+
COINBASE_PRIVATE_KEY= # from coinbase developer portal
98+
# if not configured it will be generated and written to runtime.character.settings.secrets.COINBASE_GENERATED_WALLET_ID and runtime.character.settings.secrets.COINBASE_GENERATED_WALLET_HEX_SEED
99+
COINBASE_GENERATED_WALLET_ID= # not your address but the wallet id from generating a wallet through the plugin
100+
COINBASE_GENERATED_WALLET_HEX_SEED= # not your address but the wallet hex seed from generating a wallet through the plugin and calling export

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ characters/
4040
packages/core/src/providers/cache
4141
packages/core/src/providers/cache/*
4242
cache/*
43+
packages/plugin-coinbase/src/plugins/transactions.csv
44+
packages/plugin-coinbase/package-lock.json

agent/src/index.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import {
2525
import { bootstrapPlugin } from "@ai16z/plugin-bootstrap";
2626
import { solanaPlugin } from "@ai16z/plugin-solana";
2727
import { nodePlugin } from "@ai16z/plugin-node";
28-
import { coinbaseCommercePlugin } from "@ai16z/plugin-coinbase";
28+
import {
29+
coinbaseCommercePlugin,
30+
coinbaseMassPaymentsPlugin,
31+
} from "@ai16z/plugin-coinbase";
2932
import Database from "better-sqlite3";
3033
import fs from "fs";
3134
import readline from "readline";
@@ -255,6 +258,12 @@ export function createAgent(
255258
process.env.COINBASE_COMMERCE_KEY
256259
? coinbaseCommercePlugin
257260
: null,
261+
(character.settings.secrets?.COINBASE_API_KEY ||
262+
process.env.COINBASE_API_KEY) &&
263+
(character.settings.secrets?.COINBASE_PRIVATE_KEY ||
264+
process.env.COINBASE_PRIVATE_KEY)
265+
? coinbaseMassPaymentsPlugin
266+
: null,
258267
].filter(Boolean),
259268
providers: [],
260269
actions: [],

docs/docs/packages/plugins.md

+214-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ Integrates Solana blockchain functionality:
196196
- `walletProvider` - Wallet management
197197
- `trustScoreProvider` - Transaction trust metrics
198198

199-
#### 5. Coinbase Commerce Plugin (`@eliza/plugin-coinbase-commerce`)
199+
#### 5. Coinbase Commerce Plugin (`@eliza/plugin-coinbase`)
200200

201201
Integrates Coinbase Commerce for payment and transaction management:
202202

@@ -211,6 +211,219 @@ This plugin enables Eliza to interact with the Coinbase Commerce API to create a
211211

212212
---
213213

214+
#### 6. Coinbase MassPayments Plugin (`@eliza/plugin-coinbase`)
215+
216+
This plugin facilitates the processing of cryptocurrency mass payouts using the Coinbase SDK. It enables the creation and management of mass payouts to multiple wallet addresses, logging all transaction details to a CSV file for further analysis.
217+
218+
**Actions:**
219+
220+
- `SEND_MASS_PAYOUT`
221+
Sends cryptocurrency mass payouts to multiple wallet addresses.
222+
- **Inputs**:
223+
- `receivingAddresses` (array of strings): Wallet addresses to receive funds.
224+
- `transferAmount` (number): Amount to send to each address (in smallest currency unit, e.g., Wei for ETH).
225+
- `assetId` (string): Cryptocurrency asset ID (e.g., `ETH`, `BTC`).
226+
- `network` (string): Blockchain network (e.g., `base`, `sol`, `eth`, `arb`, `pol`).
227+
- **Outputs**: Logs transaction results (success/failure) in a CSV file.
228+
- **Example**:
229+
```json
230+
{
231+
"receivingAddresses": [
232+
"0xA0ba2ACB5846A54834173fB0DD9444F756810f06",
233+
"0xF14F2c49aa90BaFA223EE074C1C33b59891826bF"
234+
],
235+
"transferAmount": 5000000000000000,
236+
"assetId": "ETH",
237+
"network": "eth"
238+
}
239+
```
240+
241+
**Providers:**
242+
243+
- `massPayoutProvider`
244+
Retrieves details of past transactions from the generated CSV file.
245+
- **Outputs**: A list of transaction records including the following fields:
246+
- `address`: Recipient wallet address.
247+
- `amount`: Amount sent.
248+
- `status`: Transaction status (`Success` or `Failed`).
249+
- `errorCode`: Error code (if any).
250+
- `transactionUrl`: URL for transaction details (if available).
251+
252+
**Description:**
253+
254+
The Coinbase MassPayments plugin streamlines cryptocurrency distribution, ensuring efficient and scalable payouts to multiple recipients on supported blockchain networks.
255+
256+
Supported networks:
257+
258+
- `base` (Base blockchain)
259+
- `sol` (Solana)
260+
- `eth` (Ethereum)
261+
- `arb` (Arbitrum)
262+
- `pol` (Polygon)
263+
264+
**Usage Instructions:**
265+
266+
1. **Configure the Plugin**
267+
Add the plugin to your character’s configuration:
268+
269+
```typescript
270+
import { coinbaseMassPaymentsPlugin } from "@eliza/plugin-coinbase-masspayments";
271+
272+
const character = {
273+
plugins: [coinbaseMassPaymentsPlugin],
274+
};
275+
```
276+
277+
2. **Ensure Secure Configuration**
278+
Set the following environment variables or runtime settings to ensure the plugin functions securely:
279+
280+
- `COINBASE_API_KEY`: API key for Coinbase SDK.
281+
- `COINBASE_PRIVATE_KEY`: Private key for secure transactions.
282+
283+
---
284+
285+
### Wallet Management
286+
287+
The plugin automatically handles wallet creation or uses an existing wallet if the required details are provided during the first run.
288+
289+
1. **Wallet Generation on First Run**
290+
If no wallet information is provided (`COINBASE_GENERATED_WALLET_HEX_SEED` and `COINBASE_GENERATED_WALLET_ID`), the plugin will:
291+
292+
- **Generate a new wallet** using the Coinbase SDK.
293+
- Automatically **export the wallet details** (`seed` and `walletId`) and securely store them in `runtime.character.settings.secrets` or other configured storage.
294+
- Log the wallet’s default address for reference.
295+
- If the character file does not exist, the wallet details are saved to a characters/charactername-seed.txt file in the characters directory with a note indicating that the user must manually add these details to settings.secrets or the .env file.
296+
297+
2. **Using an Existing Wallet**
298+
If wallet information is available during the first run:
299+
- Provide `COINBASE_GENERATED_WALLET_HEX_SEED` and `COINBASE_GENERATED_WALLET_ID` via `runtime.character.settings.secrets` or environment variables.
300+
- The plugin will **import the wallet** and use it for processing mass payouts.
301+
302+
---
303+
304+
### Required Configurations
305+
306+
The following configurations must be provided for wallet management:
307+
308+
- **Environment Variables or Secrets**:
309+
- `COINBASE_GENERATED_WALLET_HEX_SEED`: Hexadecimal seed of the wallet.
310+
- `COINBASE_GENERATED_WALLET_ID`: Unique wallet ID.
311+
- These variables must be securely stored in `runtime.character.settings.secrets` or as environment variables.
312+
313+
---
314+
315+
### Wallet Creation Process
316+
317+
1. **Automatic Wallet Creation**
318+
When no wallet details are available:
319+
320+
- A new wallet is created using the Coinbase SDK.
321+
- The wallet’s `seed` and `walletId` are retrieved using the following logic:
322+
```typescript
323+
const walletData: WalletData = wallet.export();
324+
runtime.character.settings.secrets.COINBASE_GENERATED_WALLET_HEX_SEED =
325+
walletData.seed;
326+
runtime.character.settings.secrets.COINBASE_GENERATED_WALLET_ID =
327+
walletData.walletId;
328+
```
329+
- The default wallet address is logged:
330+
```typescript
331+
const walletAddress = wallet.getDefaultAddress();
332+
elizaLogger.log("Created and stored new wallet:", walletAddress);
333+
```
334+
335+
2. **Using Existing Wallet Details**
336+
When the wallet details are provided:
337+
- The wallet is imported using the following logic:
338+
```typescript
339+
wallet = await Wallet.import({
340+
seed: storedSeed,
341+
walletId: storedWalletId,
342+
});
343+
elizaLogger.log("Imported existing wallet:", wallet.getDefaultAddress());
344+
```
345+
346+
---
347+
348+
### Example Configuration
349+
350+
#### Automatic Wallet Generation:
351+
352+
No existing wallet information is passed. The plugin creates and stores a new wallet:
353+
354+
```typescript
355+
runtime.character.settings.secrets = {
356+
// Empty settings for first run
357+
};
358+
```
359+
360+
Output Log:
361+
362+
```plaintext
363+
[INFO] Created and stored new wallet: 0x1234567890abcdef1234567890abcdef12345678
364+
```
365+
366+
#### Using Existing Wallet Information:
367+
368+
Existing wallet details are passed into the runtime:
369+
370+
```typescript
371+
runtime.character.settings.secrets = {
372+
COINBASE_GENERATED_WALLET_HEX_SEED:
373+
"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
374+
COINBASE_GENERATED_WALLET_ID: "wallet-id-123",
375+
};
376+
```
377+
378+
Output Log:
379+
380+
```plaintext
381+
[INFO] Imported existing wallet: 0x1234567890abcdef1234567890abcdef12345678
382+
```
383+
384+
---
385+
386+
3. **Example Call**
387+
An example of using the `SEND_MASS_PAYOUT` action:
388+
389+
```typescript
390+
const response = await runtime.triggerAction("SEND_MASS_PAYOUT", {
391+
receivingAddresses: [
392+
"0xA0ba2ACB5846A54834173fB0DD9444F756810f06",
393+
"0xF14F2c49aa90BaFA223EE074C1C33b59891826bF",
394+
],
395+
transferAmount: 5000000000000000, // 0.005 ETH
396+
assetId: "ETH",
397+
network: "eth",
398+
});
399+
console.log("Mass payout response:", response);
400+
```
401+
402+
4. **Transaction Logging**
403+
All transactions (successful and failed) are logged to a `transactions.csv` file in the plugins working directory:
404+
```plaintext
405+
Address,Amount,Status,Error Code,Transaction URL
406+
0xA0ba2ACB5846A54834173fB0DD9444F756810f06,5000000000000000,Success,,https://etherscan.io/tx/0x...
407+
```
408+
409+
**Example Output:**
410+
411+
When successful, a response similar to the following will be returned:
412+
413+
```json
414+
{
415+
"text": "Mass payouts completed successfully.\n- Successful Transactions: 2\n- Failed Transactions: 0\nCheck the CSV file for more details."
416+
}
417+
```
418+
419+
**Best Practices:**
420+
421+
- **Secure Secrets Storage**: Ensure `COINBASE_API_KEY` and `COINBASE_PRIVATE_KEY` are stored securely in `runtime.character.settings.secrets` or environment variables. Either add `COINBASE_GENERATED_WALLET_HEX_SEED`, and `COINBASE_GENERATED_WALLET_ID` from a previous run, or it will be dynamically created
422+
- **Validation**: Always validate input parameters, especially `receivingAddresses` and `network`, to ensure compliance with expected formats and supported networks.
423+
- **Error Handling**: Monitor logs for failed transactions or errors in the payout process and adjust retry logic as needed.
424+
425+
---
426+
214427
### Writing Custom Plugins
215428

216429
Create a new plugin by implementing the Plugin interface:

package.json

+7-6
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"test": "bash ./scripts/test.sh"
2424
},
2525
"devDependencies": {
26-
"@commitlint/cli": "18.6.1",
27-
"@commitlint/config-conventional": "18.6.3",
26+
"@commitlint/cli": "^18.4.4",
27+
"@commitlint/config-conventional": "^18.4.4",
2828
"lerna": "8.1.5",
2929
"only-allow": "1.2.1",
3030
"concurrently": "9.1.0",
@@ -34,7 +34,6 @@
3434
"typescript": "5.6.3",
3535
"vite": "5.4.11",
3636
"vitest": "2.1.5"
37-
3837
},
3938
"pnpm": {
4039
"overrides": {
@@ -46,9 +45,11 @@
4645
},
4746
"dependencies": {
4847
"ollama-ai-provider": "0.16.1",
49-
"optional": "0.1.4",
50-
"sharp": "0.33.5",
51-
"tslog": "4.9.3"
48+
"@coinbase/coinbase-sdk": "^0.10.0",
49+
"csv-parse": "^5.6.0",
50+
"optional": "^0.1.4",
51+
"sharp": "^0.33.5",
52+
"tslog": "^4.9.3"
5253
},
5354
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee"
5455
}

0 commit comments

Comments
 (0)