@coinbase/agentkit 0.2.1 → 0.2.2-nightly.20250221.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -8
- package/dist/action-providers/alchemy/alchemyTokenPricesActionProvider.d.ts +1 -1
- package/dist/action-providers/alchemy/alchemyTokenPricesActionProvider.js +9 -9
- package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +5 -3
- package/dist/action-providers/cdp/cdpApiActionProvider.js +15 -4
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +14 -2
- package/dist/action-providers/cdp/cdpWalletActionProvider.d.ts +2 -2
- package/dist/action-providers/cdp/cdpWalletActionProvider.js +6 -3
- package/dist/action-providers/cdp/cdpWalletActionProvider.test.js +8 -0
- package/dist/action-providers/erc20/erc20ActionProvider.d.ts +2 -2
- package/dist/action-providers/erc20/erc20ActionProvider.js +2 -2
- package/dist/action-providers/erc20/erc20ActionProvider.test.js +8 -0
- package/dist/action-providers/farcaster/farcasterActionProvider.d.ts +2 -2
- package/dist/action-providers/farcaster/farcasterActionProvider.js +2 -2
- package/dist/action-providers/farcaster/farcasterActionProvider.test.js +8 -0
- package/dist/action-providers/index.d.ts +2 -0
- package/dist/action-providers/index.js +2 -0
- package/dist/action-providers/jupiter/index.d.ts +1 -0
- package/dist/action-providers/jupiter/index.js +17 -0
- package/dist/action-providers/jupiter/jupiterActionProvider.d.ts +36 -0
- package/dist/action-providers/jupiter/jupiterActionProvider.js +115 -0
- package/dist/action-providers/jupiter/jupiterActionProvider.test.d.ts +1 -0
- package/dist/action-providers/jupiter/jupiterActionProvider.test.js +146 -0
- package/dist/action-providers/jupiter/schemas.d.ts +20 -0
- package/dist/action-providers/jupiter/schemas.js +20 -0
- package/dist/action-providers/spl/splActionProvider.js +23 -10
- package/dist/action-providers/spl/splActionProvider.test.js +47 -10
- package/dist/action-providers/wow/constants.js +1 -1
- package/dist/action-providers/wow/wowActionProvider.d.ts +4 -4
- package/dist/action-providers/wow/wowActionProvider.js +19 -19
- package/dist/action-providers/wow/wowActionProvider.test.js +14 -10
- package/dist/agentkit.js +8 -0
- package/dist/analytics/sendAnalyticsEvent.js +1 -0
- package/dist/wallet-providers/cdpWalletProvider.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ AgentKit is a framework for easily enabling AI agents to take actions onchain. I
|
|
|
35
35
|
- [Network Configuration](#solana-network-configuration)
|
|
36
36
|
- [RPC URL Configuration](#rpc-url-configuration)
|
|
37
37
|
- [PrivyWalletProvider](#privywalletprovider-solana)
|
|
38
|
+
- [Connection Configuration](#connection-configuration)
|
|
38
39
|
- [Authorization Keys](#authorization-keys)
|
|
39
40
|
- [Exporting Privy Wallet information](#exporting-privy-wallet-information)
|
|
40
41
|
- [Contributing](#contributing)
|
|
@@ -293,6 +294,15 @@ const agent = createReactAgent({
|
|
|
293
294
|
</tr>
|
|
294
295
|
</table>
|
|
295
296
|
</details>
|
|
297
|
+
<details>
|
|
298
|
+
<summary><strong>Jupiter</strong></summary>
|
|
299
|
+
<table width="100%">
|
|
300
|
+
<tr>
|
|
301
|
+
<td width="200"><code>swap</code></td>
|
|
302
|
+
<td width="768">Swap tokens on Solana using the Jupiter DEX aggregator.</td>
|
|
303
|
+
</tr>
|
|
304
|
+
</table>
|
|
305
|
+
</details>
|
|
296
306
|
|
|
297
307
|
## Creating an Action Provider
|
|
298
308
|
|
|
@@ -559,10 +569,10 @@ const walletProvider = new ViemWalletProvider(client, {
|
|
|
559
569
|
The `PrivyWalletProvider` is a wallet provider that uses [Privy Server Wallets](https://docs.privy.io/guide/server-wallets/). This implementation extends the `ViemWalletProvider`.
|
|
560
570
|
|
|
561
571
|
```typescript
|
|
562
|
-
import { PrivyWalletProvider } from "@coinbase/agentkit";
|
|
572
|
+
import { PrivyWalletProvider, PrivyWalletConfig } from "@coinbase/agentkit";
|
|
563
573
|
|
|
564
574
|
// Configure Wallet Provider
|
|
565
|
-
const config = {
|
|
575
|
+
const config: PrivyWalletConfig = {
|
|
566
576
|
appId: "PRIVY_APP_ID",
|
|
567
577
|
appSecret: "PRIVY_APP_SECRET",
|
|
568
578
|
chainId: "84532", // base-sepolia
|
|
@@ -578,7 +588,7 @@ const walletProvider = await PrivyWalletProvider.configureWithWallet(config);
|
|
|
578
588
|
|
|
579
589
|
Privy offers the option to use authorization keys to secure your server wallets.
|
|
580
590
|
|
|
581
|
-
You can manage authorization keys from your [Privy dashboard](https://dashboard.privy.io/account)
|
|
591
|
+
You can manage authorization keys from your [Privy dashboard](https://dashboard.privy.io/account).
|
|
582
592
|
|
|
583
593
|
When using authorization keys, you must provide the `authorizationPrivateKey` and `authorizationKeyId` parameters to the `configureWithWallet` method if you are creating a new wallet. Please note that when creating a key, if you enable "Create and modify wallets", you will be required to use that key when creating new wallets via the PrivyWalletProvider.
|
|
584
594
|
|
|
@@ -601,11 +611,14 @@ const walletData = await walletProvider.exportWallet();
|
|
|
601
611
|
|
|
602
612
|
SVM:
|
|
603
613
|
- [SolanaKeypairWalletProvider](https://github.com/coinbase/agentkit/blob/main/typescript/agentkit/src/wallet-providers/solanaKeypairWalletProvider.ts)
|
|
614
|
+
- [PrivyWalletProvider](https://github.com/coinbase/agentkit/blob/main/typescript/agentkit/src/wallet-providers/privySvmWalletProvider.ts)
|
|
604
615
|
|
|
605
616
|
### SolanaKeypairWalletProvider
|
|
606
617
|
|
|
607
618
|
The `SolanaKeypairWalletProvider` is a wallet provider that uses the API [Solana web3.js](https://solana-labs.github.io/solana-web3.js/).
|
|
608
619
|
|
|
620
|
+
NOTE: It is highly recommended to use a dedicated RPC provider. See [here](https://solana.com/rpc) for more info on Solana RPC infrastructure, and see [here](#rpc-url-configuration) for instructions on configuring `SolanaKeypairWalletProvider` with a custom RPC URL.
|
|
621
|
+
|
|
609
622
|
#### Solana Network Configuration
|
|
610
623
|
|
|
611
624
|
The `SolanaKeypairWalletProvider` can be configured to use a specific network by passing the `networkId` parameter to the `fromNetwork` method. The `networkId` is the ID of the Solana network you want to use. Valid values are `solana-mainnet`, `solana-devnet` and `solana-testnet`.
|
|
@@ -641,11 +654,13 @@ const walletProvider = await SolanaKeypairWalletProvider.fromRpcUrl(network, pri
|
|
|
641
654
|
|
|
642
655
|
The `PrivyWalletProvider` is a wallet provider that uses [Privy Server Wallets](https://docs.privy.io/guide/server-wallets/).
|
|
643
656
|
|
|
657
|
+
NOTE: It is highly recommended to use a dedicated RPC provider. See [here](https://solana.com/rpc) for more info on Solana RPC infrastructure, and see [here](#connection-configuration) for instructions on configuring `PrivyWalletProvider` with a custom RPC URL.
|
|
658
|
+
|
|
644
659
|
```typescript
|
|
645
|
-
import { PrivyWalletProvider } from "@coinbase/agentkit";
|
|
660
|
+
import { PrivyWalletProvider, PrivyWalletConfig } from "@coinbase/agentkit";
|
|
646
661
|
|
|
647
662
|
// Configure Wallet Provider
|
|
648
|
-
const config = {
|
|
663
|
+
const config: PrivyWalletConfig = {
|
|
649
664
|
appId: "PRIVY_APP_ID",
|
|
650
665
|
appSecret: "PRIVY_APP_SECRET",
|
|
651
666
|
chainType: "solana", // optional, defaults to "evm". Make sure to set this to "solana" if you want to use Solana!
|
|
@@ -658,15 +673,17 @@ const config = {
|
|
|
658
673
|
const walletProvider = await PrivyWalletProvider.configureWithWallet(config);
|
|
659
674
|
```
|
|
660
675
|
|
|
676
|
+
#### Connection Configuration
|
|
677
|
+
|
|
661
678
|
Optionally, you can configure your own `@solana/web3.js` connection by passing the `connection` parameter to the `configureWithWallet` method.
|
|
662
679
|
|
|
663
680
|
```typescript
|
|
664
|
-
import { PrivyWalletProvider } from "@coinbase/agentkit";
|
|
681
|
+
import { PrivyWalletProvider, PrivyWalletConfig } from "@coinbase/agentkit";
|
|
665
682
|
|
|
666
683
|
const connection = new Connection("YOUR_RPC_URL");
|
|
667
684
|
|
|
668
685
|
// Configure Wallet Provider
|
|
669
|
-
const config = {
|
|
686
|
+
const config: PrivyWalletConfig = {
|
|
670
687
|
appId: "PRIVY_APP_ID",
|
|
671
688
|
appSecret: "PRIVY_APP_SECRET",
|
|
672
689
|
connection,
|
|
@@ -684,7 +701,7 @@ const walletProvider = await PrivyWalletProvider.configureWithWallet(config);
|
|
|
684
701
|
|
|
685
702
|
Privy offers the option to use authorization keys to secure your server wallets.
|
|
686
703
|
|
|
687
|
-
You can manage authorization keys from your [Privy dashboard](https://dashboard.privy.io/account)
|
|
704
|
+
You can manage authorization keys from your [Privy dashboard](https://dashboard.privy.io/account).
|
|
688
705
|
|
|
689
706
|
When using authorization keys, you must provide the `authorizationPrivateKey` and `authorizationKeyId` parameters to the `configureWithWallet` method if you are creating a new wallet. Please note that when creating a key, if you enable "Create and modify wallets", you will be required to use that key when creating new wallets via the PrivyWalletProvider.
|
|
690
707
|
|
|
@@ -44,7 +44,7 @@ export declare class AlchemyTokenPricesActionProvider extends ActionProvider {
|
|
|
44
44
|
*
|
|
45
45
|
* @returns Always returns true.
|
|
46
46
|
*/
|
|
47
|
-
supportsNetwork()
|
|
47
|
+
supportsNetwork: () => boolean;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Factory function to create a new AlchemyTokenPricesActionProvider instance.
|
|
@@ -27,6 +27,15 @@ class AlchemyTokenPricesActionProvider extends actionProvider_1.ActionProvider {
|
|
|
27
27
|
*/
|
|
28
28
|
constructor(config = {}) {
|
|
29
29
|
super("alchemyTokenPrices", []);
|
|
30
|
+
/**
|
|
31
|
+
* Checks if the Alchemy Prices action provider supports the given network.
|
|
32
|
+
* Since the API works with multiple networks, this always returns true.
|
|
33
|
+
*
|
|
34
|
+
* @returns Always returns true.
|
|
35
|
+
*/
|
|
36
|
+
this.supportsNetwork = () => {
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
30
39
|
config.apiKey || (config.apiKey = process.env.ALCHEMY_API_KEY);
|
|
31
40
|
if (!config.apiKey) {
|
|
32
41
|
throw new Error("ALCHEMY_API_KEY is not configured.");
|
|
@@ -91,15 +100,6 @@ class AlchemyTokenPricesActionProvider extends actionProvider_1.ActionProvider {
|
|
|
91
100
|
return `Error fetching token prices by address: ${error}`;
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
|
-
/**
|
|
95
|
-
* Checks if the Alchemy Prices action provider supports the given network.
|
|
96
|
-
* Since the API works with multiple networks, this always returns true.
|
|
97
|
-
*
|
|
98
|
-
* @returns Always returns true.
|
|
99
|
-
*/
|
|
100
|
-
supportsNetwork() {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
103
|
}
|
|
104
104
|
exports.AlchemyTokenPricesActionProvider = AlchemyTokenPricesActionProvider;
|
|
105
105
|
__decorate([
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ActionProvider } from "../actionProvider";
|
|
3
3
|
import { Network } from "../../network";
|
|
4
|
-
import { CdpProviderConfig,
|
|
4
|
+
import { CdpProviderConfig, WalletProvider } from "../../wallet-providers";
|
|
5
5
|
import { AddressReputationSchema, RequestFaucetFundsSchema } from "./schemas";
|
|
6
6
|
/**
|
|
7
7
|
* CdpApiActionProvider is an action provider for CDP API.
|
|
8
8
|
*
|
|
9
9
|
* This provider is used for any action that uses the CDP API, but does not require a CDP Wallet.
|
|
10
10
|
*/
|
|
11
|
-
export declare class CdpApiActionProvider extends ActionProvider<
|
|
11
|
+
export declare class CdpApiActionProvider extends ActionProvider<WalletProvider> {
|
|
12
12
|
/**
|
|
13
13
|
* Constructor for the CdpApiActionProvider class.
|
|
14
14
|
*
|
|
@@ -29,10 +29,12 @@ export declare class CdpApiActionProvider extends ActionProvider<EvmWalletProvid
|
|
|
29
29
|
* @param args - The input arguments for the action.
|
|
30
30
|
* @returns A confirmation message with transaction details.
|
|
31
31
|
*/
|
|
32
|
-
faucet(walletProvider:
|
|
32
|
+
faucet(walletProvider: WalletProvider, args: z.infer<typeof RequestFaucetFundsSchema>): Promise<string>;
|
|
33
33
|
/**
|
|
34
34
|
* Checks if the Cdp action provider supports the given network.
|
|
35
35
|
*
|
|
36
|
+
* NOTE: Network scoping is done at the action implementation level
|
|
37
|
+
*
|
|
36
38
|
* @param _ - The network to check.
|
|
37
39
|
* @returns True if the Cdp action provider supports the network, false otherwise.
|
|
38
40
|
*/
|
|
@@ -33,6 +33,8 @@ class CdpApiActionProvider extends actionProvider_1.ActionProvider {
|
|
|
33
33
|
/**
|
|
34
34
|
* Checks if the Cdp action provider supports the given network.
|
|
35
35
|
*
|
|
36
|
+
* NOTE: Network scoping is done at the action implementation level
|
|
37
|
+
*
|
|
36
38
|
* @param _ - The network to check.
|
|
37
39
|
* @returns True if the Cdp action provider supports the network, false otherwise.
|
|
38
40
|
*/
|
|
@@ -40,7 +42,7 @@ class CdpApiActionProvider extends actionProvider_1.ActionProvider {
|
|
|
40
42
|
if (config.apiKeyName && config.apiKeyPrivateKey) {
|
|
41
43
|
coinbase_sdk_1.Coinbase.configure({
|
|
42
44
|
apiKeyName: config.apiKeyName,
|
|
43
|
-
privateKey: config.apiKeyPrivateKey,
|
|
45
|
+
privateKey: config.apiKeyPrivateKey?.replace(/\\n/g, "\n"),
|
|
44
46
|
source: "agentkit",
|
|
45
47
|
sourceVersion: package_json_1.version,
|
|
46
48
|
});
|
|
@@ -56,6 +58,9 @@ class CdpApiActionProvider extends actionProvider_1.ActionProvider {
|
|
|
56
58
|
* @returns A string containing reputation data or error message
|
|
57
59
|
*/
|
|
58
60
|
async addressReputation(args) {
|
|
61
|
+
if (args.network.includes("solana")) {
|
|
62
|
+
return "Address reputation is only supported on Ethereum networks.";
|
|
63
|
+
}
|
|
59
64
|
try {
|
|
60
65
|
const address = new coinbase_sdk_1.ExternalAddress(args.network, args.address);
|
|
61
66
|
const reputation = await address.reputation();
|
|
@@ -73,10 +78,14 @@ class CdpApiActionProvider extends actionProvider_1.ActionProvider {
|
|
|
73
78
|
* @returns A confirmation message with transaction details.
|
|
74
79
|
*/
|
|
75
80
|
async faucet(walletProvider, args) {
|
|
81
|
+
const network = walletProvider.getNetwork();
|
|
82
|
+
if (network.networkId !== "base-sepolia" && network.networkId !== "solana-devnet") {
|
|
83
|
+
return `Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.`;
|
|
84
|
+
}
|
|
76
85
|
try {
|
|
77
86
|
const address = new coinbase_sdk_1.ExternalAddress(walletProvider.getNetwork().networkId, walletProvider.getAddress());
|
|
78
87
|
const faucetTx = await address.faucet(args.assetId || undefined);
|
|
79
|
-
const result = await faucetTx.wait();
|
|
88
|
+
const result = await faucetTx.wait({ timeoutSeconds: 60 });
|
|
80
89
|
return `Received ${args.assetId || "ETH"} from the faucet. Transaction: ${result.getTransactionLink()}`;
|
|
81
90
|
}
|
|
82
91
|
catch (error) {
|
|
@@ -104,13 +113,15 @@ __decorate([
|
|
|
104
113
|
(0, actionDecorator_1.CreateAction)({
|
|
105
114
|
name: "request_faucet_funds",
|
|
106
115
|
description: `This tool will request test tokens from the faucet for the default address in the wallet. It takes the wallet and asset ID as input.
|
|
107
|
-
|
|
116
|
+
Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.
|
|
117
|
+
If fauceting on 'base-sepolia', user can only provide asset ID 'eth' or 'usdc', if no asset ID is provided, the faucet will default to 'eth'.
|
|
118
|
+
If fauceting on 'solana-devnet', user can only provide asset ID 'sol', if no asset ID is provided, the faucet will default to 'sol'.
|
|
108
119
|
You are not allowed to faucet with any other network or asset ID. If you are on another network, suggest that the user sends you some ETH
|
|
109
120
|
from another wallet and provide the user with your wallet details.`,
|
|
110
121
|
schema: schemas_1.RequestFaucetFundsSchema,
|
|
111
122
|
}),
|
|
112
123
|
__metadata("design:type", Function),
|
|
113
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
124
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
114
125
|
__metadata("design:returntype", Promise)
|
|
115
126
|
], CdpApiActionProvider.prototype, "faucet", null);
|
|
116
127
|
const cdpApiActionProvider = (config = {}) => new CdpApiActionProvider(config);
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const cdpApiActionProvider_1 = require("./cdpApiActionProvider");
|
|
4
4
|
const schemas_1 = require("./schemas");
|
|
5
|
-
// Mock the entire module
|
|
6
5
|
jest.mock("@coinbase/coinbase-sdk");
|
|
7
|
-
// Get the mocked constructor
|
|
8
6
|
const { ExternalAddress } = jest.requireMock("@coinbase/coinbase-sdk");
|
|
9
7
|
describe("CDP API Action Provider Input Schemas", () => {
|
|
10
8
|
describe("Address Reputation Schema", () => {
|
|
@@ -93,6 +91,14 @@ describe("CDP API Action Provider", () => {
|
|
|
93
91
|
expect(mockExternalAddressInstance.reputation).toHaveBeenCalledTimes(1);
|
|
94
92
|
expect(result).toBe(`Error checking address reputation: ${error}`);
|
|
95
93
|
});
|
|
94
|
+
it("should return error if not on Ethereum network", async () => {
|
|
95
|
+
const args = {
|
|
96
|
+
address: "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83",
|
|
97
|
+
network: "solana-devnet",
|
|
98
|
+
};
|
|
99
|
+
const result = await actionProvider.addressReputation(args);
|
|
100
|
+
expect(result).toBe("Address reputation is only supported on Ethereum networks.");
|
|
101
|
+
});
|
|
96
102
|
});
|
|
97
103
|
describe("faucet", () => {
|
|
98
104
|
beforeEach(() => {
|
|
@@ -130,5 +136,11 @@ describe("CDP API Action Provider", () => {
|
|
|
130
136
|
const result = await actionProvider.faucet(mockWallet, args);
|
|
131
137
|
expect(result).toBe(`Error requesting faucet funds: ${error}`);
|
|
132
138
|
});
|
|
139
|
+
it("should return error if not on base-sepolia or solana-devnet", async () => {
|
|
140
|
+
mockWallet.getNetwork.mockReturnValue({ networkId: "solana-mainnet", protocolFamily: "svm" });
|
|
141
|
+
const args = {};
|
|
142
|
+
const result = await actionProvider.faucet(mockWallet, args);
|
|
143
|
+
expect(result).toBe("Faucet is only allowed on 'base-sepolia' or 'solana-devnet'.");
|
|
144
|
+
});
|
|
133
145
|
});
|
|
134
146
|
});
|
|
@@ -50,9 +50,9 @@ export declare class CdpWalletActionProvider extends ActionProvider<CdpWalletPro
|
|
|
50
50
|
/**
|
|
51
51
|
* Checks if the Cdp action provider supports the given network.
|
|
52
52
|
*
|
|
53
|
-
* @param
|
|
53
|
+
* @param network - The network to check.
|
|
54
54
|
* @returns True if the Cdp action provider supports the network, false otherwise.
|
|
55
55
|
*/
|
|
56
|
-
supportsNetwork: (
|
|
56
|
+
supportsNetwork: (network: Network) => boolean;
|
|
57
57
|
}
|
|
58
58
|
export declare const cdpWalletActionProvider: (config?: CdpProviderConfig) => CdpWalletActionProvider;
|
|
@@ -33,12 +33,15 @@ class CdpWalletActionProvider extends actionProvider_1.ActionProvider {
|
|
|
33
33
|
/**
|
|
34
34
|
* Checks if the Cdp action provider supports the given network.
|
|
35
35
|
*
|
|
36
|
-
* @param
|
|
36
|
+
* @param network - The network to check.
|
|
37
37
|
* @returns True if the Cdp action provider supports the network, false otherwise.
|
|
38
38
|
*/
|
|
39
|
-
this.supportsNetwork = (
|
|
39
|
+
this.supportsNetwork = (network) => network.protocolFamily === "evm";
|
|
40
40
|
if (config.apiKeyName && config.apiKeyPrivateKey) {
|
|
41
|
-
coinbase_sdk_1.Coinbase.configure({
|
|
41
|
+
coinbase_sdk_1.Coinbase.configure({
|
|
42
|
+
apiKeyName: config.apiKeyName,
|
|
43
|
+
privateKey: config.apiKeyPrivateKey?.replace(/\\n/g, "\n"),
|
|
44
|
+
});
|
|
42
45
|
}
|
|
43
46
|
else {
|
|
44
47
|
coinbase_sdk_1.Coinbase.configureFromJson();
|
|
@@ -256,4 +256,12 @@ describe("CDP Wallet Action Provider", () => {
|
|
|
256
256
|
expect(result).toBe(`Error trading assets: ${error}`);
|
|
257
257
|
});
|
|
258
258
|
});
|
|
259
|
+
describe("supportsNetwork", () => {
|
|
260
|
+
it("should return true when protocolFamily is evm", () => {
|
|
261
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "evm" })).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
it("should return false when protocolFamily is not evm", () => {
|
|
264
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "solana" })).toBe(false);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
259
267
|
});
|
|
@@ -30,9 +30,9 @@ export declare class ERC20ActionProvider extends ActionProvider<EvmWalletProvide
|
|
|
30
30
|
/**
|
|
31
31
|
* Checks if the ERC20 action provider supports the given network.
|
|
32
32
|
*
|
|
33
|
-
* @param
|
|
33
|
+
* @param network - The network to check.
|
|
34
34
|
* @returns True if the ERC20 action provider supports the network, false otherwise.
|
|
35
35
|
*/
|
|
36
|
-
supportsNetwork: (
|
|
36
|
+
supportsNetwork: (network: Network) => boolean;
|
|
37
37
|
}
|
|
38
38
|
export declare const erc20ActionProvider: () => ERC20ActionProvider;
|
|
@@ -29,10 +29,10 @@ class ERC20ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
29
29
|
/**
|
|
30
30
|
* Checks if the ERC20 action provider supports the given network.
|
|
31
31
|
*
|
|
32
|
-
* @param
|
|
32
|
+
* @param network - The network to check.
|
|
33
33
|
* @returns True if the ERC20 action provider supports the network, false otherwise.
|
|
34
34
|
*/
|
|
35
|
-
this.supportsNetwork = (
|
|
35
|
+
this.supportsNetwork = (network) => network.protocolFamily === "evm";
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Gets the balance of an ERC20 token.
|
|
@@ -114,4 +114,12 @@ describe("Transfer Action", () => {
|
|
|
114
114
|
});
|
|
115
115
|
expect(response).toContain(`Error transferring the asset: ${error}`);
|
|
116
116
|
});
|
|
117
|
+
describe("supportsNetwork", () => {
|
|
118
|
+
it("should return true when protocolFamily is evm", () => {
|
|
119
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "evm" })).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it("should return false when protocolFamily is not evm", () => {
|
|
122
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "solana" })).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
117
125
|
});
|
|
@@ -49,9 +49,9 @@ export declare class FarcasterActionProvider extends ActionProvider {
|
|
|
49
49
|
/**
|
|
50
50
|
* Checks if the Farcaster action provider supports the given network.
|
|
51
51
|
*
|
|
52
|
-
* @param
|
|
52
|
+
* @param network - The network to check.
|
|
53
53
|
* @returns True if the Farcaster action provider supports the network, false otherwise.
|
|
54
54
|
*/
|
|
55
|
-
supportsNetwork: (
|
|
55
|
+
supportsNetwork: (network: Network) => boolean;
|
|
56
56
|
}
|
|
57
57
|
export declare const farcasterActionProvider: (config?: FarcasterActionProviderConfig) => FarcasterActionProvider;
|
|
@@ -28,10 +28,10 @@ class FarcasterActionProvider extends actionProvider_1.ActionProvider {
|
|
|
28
28
|
/**
|
|
29
29
|
* Checks if the Farcaster action provider supports the given network.
|
|
30
30
|
*
|
|
31
|
-
* @param
|
|
31
|
+
* @param network - The network to check.
|
|
32
32
|
* @returns True if the Farcaster action provider supports the network, false otherwise.
|
|
33
33
|
*/
|
|
34
|
-
this.supportsNetwork = (
|
|
34
|
+
this.supportsNetwork = (network) => network.protocolFamily === "evm";
|
|
35
35
|
const neynarApiKey = config.neynarApiKey || process.env.NEYNAR_API_KEY;
|
|
36
36
|
const signerUuid = config.signerUuid || process.env.NEYNAR_MANAGER_SIGNER;
|
|
37
37
|
const agentFid = config.agentFid || process.env.AGENT_FID;
|
|
@@ -140,4 +140,12 @@ describe("Farcaster Action Provider", () => {
|
|
|
140
140
|
process.env = originalEnv;
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
|
+
describe("supportsNetwork", () => {
|
|
144
|
+
it("should return true when protocolFamily is evm", () => {
|
|
145
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "evm" })).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it("should return false when protocolFamily is not evm", () => {
|
|
148
|
+
expect(actionProvider.supportsNetwork({ protocolFamily: "solana" })).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
143
151
|
});
|
|
@@ -7,6 +7,7 @@ export * from "./cdp";
|
|
|
7
7
|
export * from "./erc20";
|
|
8
8
|
export * from "./erc721";
|
|
9
9
|
export * from "./farcaster";
|
|
10
|
+
export * from "./jupiter";
|
|
10
11
|
export * from "./pyth";
|
|
11
12
|
export * from "./moonwell";
|
|
12
13
|
export * from "./morpho";
|
|
@@ -14,3 +15,4 @@ export * from "./spl";
|
|
|
14
15
|
export * from "./twitter";
|
|
15
16
|
export * from "./wallet";
|
|
16
17
|
export * from "./weth";
|
|
18
|
+
export * from "./wow";
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./cdp"), exports);
|
|
|
23
23
|
__exportStar(require("./erc20"), exports);
|
|
24
24
|
__exportStar(require("./erc721"), exports);
|
|
25
25
|
__exportStar(require("./farcaster"), exports);
|
|
26
|
+
__exportStar(require("./jupiter"), exports);
|
|
26
27
|
__exportStar(require("./pyth"), exports);
|
|
27
28
|
__exportStar(require("./moonwell"), exports);
|
|
28
29
|
__exportStar(require("./morpho"), exports);
|
|
@@ -30,3 +31,4 @@ __exportStar(require("./spl"), exports);
|
|
|
30
31
|
__exportStar(require("./twitter"), exports);
|
|
31
32
|
__exportStar(require("./wallet"), exports);
|
|
32
33
|
__exportStar(require("./weth"), exports);
|
|
34
|
+
__exportStar(require("./wow"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./jupiterActionProvider";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./jupiterActionProvider"), exports);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ActionProvider } from "../actionProvider";
|
|
2
|
+
import { Network } from "../../network";
|
|
3
|
+
import { SvmWalletProvider } from "../../wallet-providers/svmWalletProvider";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { SwapTokenSchema } from "./schemas";
|
|
6
|
+
/**
|
|
7
|
+
* JupiterActionProvider handles token swaps using Jupiter's API.
|
|
8
|
+
*/
|
|
9
|
+
export declare class JupiterActionProvider extends ActionProvider<SvmWalletProvider> {
|
|
10
|
+
/**
|
|
11
|
+
* Initializes Jupiter API client.
|
|
12
|
+
*/
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Swaps tokens using Jupiter's API.
|
|
16
|
+
*
|
|
17
|
+
* @param walletProvider - The wallet provider to use for the swap
|
|
18
|
+
* @param args - Swap parameters including input token, output token, and amount
|
|
19
|
+
* @returns A message indicating success or failure with transaction details
|
|
20
|
+
*/
|
|
21
|
+
swap(walletProvider: SvmWalletProvider, args: z.infer<typeof SwapTokenSchema>): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Checks if the action provider supports the given network.
|
|
24
|
+
* Only supports Solana networks.
|
|
25
|
+
*
|
|
26
|
+
* @param network - The network to check support for
|
|
27
|
+
* @returns True if the network is a Solana network
|
|
28
|
+
*/
|
|
29
|
+
supportsNetwork(network: Network): boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Factory function to create a new JupiterActionProvider instance.
|
|
33
|
+
*
|
|
34
|
+
* @returns A new JupiterActionProvider instance
|
|
35
|
+
*/
|
|
36
|
+
export declare const jupiterActionProvider: () => JupiterActionProvider;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.jupiterActionProvider = exports.JupiterActionProvider = void 0;
|
|
13
|
+
const actionProvider_1 = require("../actionProvider");
|
|
14
|
+
const svmWalletProvider_1 = require("../../wallet-providers/svmWalletProvider");
|
|
15
|
+
const zod_1 = require("zod");
|
|
16
|
+
const actionDecorator_1 = require("../actionDecorator");
|
|
17
|
+
const schemas_1 = require("./schemas");
|
|
18
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
19
|
+
const api_1 = require("@jup-ag/api");
|
|
20
|
+
/**
|
|
21
|
+
* JupiterActionProvider handles token swaps using Jupiter's API.
|
|
22
|
+
*/
|
|
23
|
+
class JupiterActionProvider extends actionProvider_1.ActionProvider {
|
|
24
|
+
/**
|
|
25
|
+
* Initializes Jupiter API client.
|
|
26
|
+
*/
|
|
27
|
+
constructor() {
|
|
28
|
+
super("jupiter", []);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Swaps tokens using Jupiter's API.
|
|
32
|
+
*
|
|
33
|
+
* @param walletProvider - The wallet provider to use for the swap
|
|
34
|
+
* @param args - Swap parameters including input token, output token, and amount
|
|
35
|
+
* @returns A message indicating success or failure with transaction details
|
|
36
|
+
*/
|
|
37
|
+
async swap(walletProvider, args) {
|
|
38
|
+
try {
|
|
39
|
+
const jupiterApi = (0, api_1.createJupiterApiClient)();
|
|
40
|
+
const userPublicKey = walletProvider.getPublicKey();
|
|
41
|
+
const inputMint = new web3_js_1.PublicKey(args.inputMint);
|
|
42
|
+
const outputMint = new web3_js_1.PublicKey(args.outputMint);
|
|
43
|
+
const { getMint } = await import("@solana/spl-token");
|
|
44
|
+
let mintInfo;
|
|
45
|
+
try {
|
|
46
|
+
mintInfo = await getMint(walletProvider.getConnection(), inputMint);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return `Failed to fetch mint info for mint address ${args.inputMint}. Error: ${error}`;
|
|
50
|
+
}
|
|
51
|
+
const amount = args.amount * 10 ** mintInfo.decimals;
|
|
52
|
+
const quoteResponse = await jupiterApi.quoteGet({
|
|
53
|
+
inputMint: inputMint.toBase58(),
|
|
54
|
+
outputMint: outputMint.toBase58(),
|
|
55
|
+
amount: amount,
|
|
56
|
+
slippageBps: args.slippageBps || 50, // 0.5% default slippage
|
|
57
|
+
});
|
|
58
|
+
if (!quoteResponse) {
|
|
59
|
+
throw new Error("Failed to get a swap quote.");
|
|
60
|
+
}
|
|
61
|
+
const swapRequest = {
|
|
62
|
+
userPublicKey: userPublicKey.toBase58(),
|
|
63
|
+
wrapAndUnwrapSol: true,
|
|
64
|
+
useSharedAccounts: true, // Optimize for low transaction costs
|
|
65
|
+
quoteResponse,
|
|
66
|
+
};
|
|
67
|
+
const swapResponse = await jupiterApi.swapPost({ swapRequest });
|
|
68
|
+
if (!swapResponse || !swapResponse.swapTransaction) {
|
|
69
|
+
throw new Error("Failed to generate swap transaction.");
|
|
70
|
+
}
|
|
71
|
+
const transactionBuffer = Buffer.from(swapResponse.swapTransaction, "base64");
|
|
72
|
+
const tx = web3_js_1.VersionedTransaction.deserialize(transactionBuffer);
|
|
73
|
+
const signature = await walletProvider.signAndSendTransaction(tx);
|
|
74
|
+
await walletProvider.waitForSignatureResult(signature);
|
|
75
|
+
return `Successfully swapped ${args.amount} tokens! Signature: ${signature}`;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return `Error swapping tokens: ${error}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Checks if the action provider supports the given network.
|
|
83
|
+
* Only supports Solana networks.
|
|
84
|
+
*
|
|
85
|
+
* @param network - The network to check support for
|
|
86
|
+
* @returns True if the network is a Solana network
|
|
87
|
+
*/
|
|
88
|
+
supportsNetwork(network) {
|
|
89
|
+
return network.protocolFamily == "svm" && network.networkId === "solana-mainnet";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.JupiterActionProvider = JupiterActionProvider;
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, actionDecorator_1.CreateAction)({
|
|
95
|
+
name: "swap",
|
|
96
|
+
description: `
|
|
97
|
+
Swaps tokens using Jupiter's DEX aggregator.
|
|
98
|
+
- Input and output tokens must be valid SPL token mints.
|
|
99
|
+
- Ensures sufficient balance before executing swap.
|
|
100
|
+
- If says "SOL" as the input or output, use the mint address So11111111111111111111111111111111111111112
|
|
101
|
+
NOTE: Only available on Solana mainnet.
|
|
102
|
+
`,
|
|
103
|
+
schema: schemas_1.SwapTokenSchema,
|
|
104
|
+
}),
|
|
105
|
+
__metadata("design:type", Function),
|
|
106
|
+
__metadata("design:paramtypes", [svmWalletProvider_1.SvmWalletProvider, void 0]),
|
|
107
|
+
__metadata("design:returntype", Promise)
|
|
108
|
+
], JupiterActionProvider.prototype, "swap", null);
|
|
109
|
+
/**
|
|
110
|
+
* Factory function to create a new JupiterActionProvider instance.
|
|
111
|
+
*
|
|
112
|
+
* @returns A new JupiterActionProvider instance
|
|
113
|
+
*/
|
|
114
|
+
const jupiterActionProvider = () => new JupiterActionProvider();
|
|
115
|
+
exports.jupiterActionProvider = jupiterActionProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
4
|
+
const jupiterActionProvider_1 = require("./jupiterActionProvider");
|
|
5
|
+
const api_1 = require("@jup-ag/api");
|
|
6
|
+
// Default SPL token decimals for tests
|
|
7
|
+
const DECIMALS = 6;
|
|
8
|
+
// Mock the @solana/web3.js module
|
|
9
|
+
jest.mock("@solana/web3.js", () => ({
|
|
10
|
+
// Preserve the actual implementation of @solana/web3.js while overriding specific methods
|
|
11
|
+
...jest.requireActual("@solana/web3.js"),
|
|
12
|
+
// Mock the Solana Connection class to prevent real network calls
|
|
13
|
+
Connection: jest.fn(),
|
|
14
|
+
// Mock the VersionedTransaction class and its deserialize method
|
|
15
|
+
VersionedTransaction: {
|
|
16
|
+
deserialize: jest.fn().mockReturnValue({
|
|
17
|
+
// Mock the sign method to prevent actual signing operations
|
|
18
|
+
sign: jest.fn(),
|
|
19
|
+
}),
|
|
20
|
+
},
|
|
21
|
+
// Mock the MessageV0 class and its compile method to return an empty object
|
|
22
|
+
MessageV0: {
|
|
23
|
+
compile: jest.fn().mockReturnValue({}),
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
// Mock the @solana/spl-token module
|
|
27
|
+
jest.mock("@solana/spl-token", () => ({
|
|
28
|
+
// Preserve the actual implementation of @solana/spl-token while overriding specific methods
|
|
29
|
+
...jest.requireActual("@solana/spl-token"),
|
|
30
|
+
// Mock getMint to always return a fixed decimal value for tokens
|
|
31
|
+
getMint: jest.fn().mockReturnValue({ decimals: DECIMALS }),
|
|
32
|
+
}));
|
|
33
|
+
// Mock the @jup-ag/api module
|
|
34
|
+
jest.mock("@jup-ag/api", () => ({
|
|
35
|
+
// Mock the createJupiterApiClient function to return an object with mocked methods
|
|
36
|
+
createJupiterApiClient: jest.fn().mockReturnValue({
|
|
37
|
+
// Mock the quoteGet method, which fetches the best swap route
|
|
38
|
+
quoteGet: jest.fn(),
|
|
39
|
+
// Mock the swapPost method, which generates the swap transaction
|
|
40
|
+
swapPost: jest.fn(),
|
|
41
|
+
}),
|
|
42
|
+
}));
|
|
43
|
+
// Mock the custom wallet provider used for Solana transactions
|
|
44
|
+
jest.mock("../../wallet-providers/svmWalletProvider");
|
|
45
|
+
describe("JupiterActionProvider", () => {
|
|
46
|
+
let actionProvider;
|
|
47
|
+
let mockWallet;
|
|
48
|
+
let mockConnection;
|
|
49
|
+
let mockJupiterApi;
|
|
50
|
+
let mockQuoteGet;
|
|
51
|
+
let mockSwapPost;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
jest.clearAllMocks(); // Reset mocks before each test to ensure no test interference
|
|
54
|
+
// Create a mock Jupiter API client with mocked methods
|
|
55
|
+
mockJupiterApi = (0, api_1.createJupiterApiClient)();
|
|
56
|
+
mockQuoteGet = mockJupiterApi.quoteGet;
|
|
57
|
+
mockSwapPost = mockJupiterApi.swapPost;
|
|
58
|
+
// Initialize the action provider
|
|
59
|
+
actionProvider = new jupiterActionProvider_1.JupiterActionProvider();
|
|
60
|
+
// Mock the Solana connection to avoid real network requests
|
|
61
|
+
mockConnection = {
|
|
62
|
+
getLatestBlockhash: jest.fn().mockResolvedValue({ blockhash: "mockedBlockhash" }),
|
|
63
|
+
};
|
|
64
|
+
// Mock the wallet provider with necessary methods
|
|
65
|
+
mockWallet = {
|
|
66
|
+
getConnection: jest.fn().mockReturnValue(mockConnection), // Return the mocked connection
|
|
67
|
+
getPublicKey: jest.fn().mockReturnValue(new web3_js_1.PublicKey("11111111111111111111111111111111")),
|
|
68
|
+
signAndSendTransaction: jest.fn().mockResolvedValue("mock-signature"),
|
|
69
|
+
waitForSignatureResult: jest.fn().mockResolvedValue({
|
|
70
|
+
context: { slot: 1234 },
|
|
71
|
+
value: { err: null },
|
|
72
|
+
}),
|
|
73
|
+
getAddress: jest.fn().mockReturnValue("11111111111111111111111111111111"),
|
|
74
|
+
getNetwork: jest.fn().mockReturnValue({ protocolFamily: "svm", networkId: "solana-mainnet" }),
|
|
75
|
+
getName: jest.fn().mockReturnValue("mock-wallet"),
|
|
76
|
+
getBalance: jest.fn().mockResolvedValue(BigInt(1000000000)),
|
|
77
|
+
nativeTransfer: jest.fn(),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
/**
|
|
81
|
+
* Test cases for the swap function of JupiterActionProvider
|
|
82
|
+
*/
|
|
83
|
+
describe("swap", () => {
|
|
84
|
+
const INPUT_MINT = "So11111111111111111111111111111111111111112"; // Mock SOL mint address
|
|
85
|
+
const OUTPUT_MINT = "BXXkv6FbfHZmKbMmy6KvaakKt6bYjhbjmhvJ92kp92Mw"; // Mock token mint address
|
|
86
|
+
const MOCK_SIGNATURE = "mock-signature";
|
|
87
|
+
// Mock arguments for swapping tokens
|
|
88
|
+
const swapArgs = {
|
|
89
|
+
inputMint: INPUT_MINT,
|
|
90
|
+
outputMint: OUTPUT_MINT,
|
|
91
|
+
amount: 1000, // User-specified amount
|
|
92
|
+
slippageBps: 50, // Slippage tolerance
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Test successful token swap execution
|
|
96
|
+
*/
|
|
97
|
+
it("should successfully swap tokens", async () => {
|
|
98
|
+
// Mock a successful quote response from Jupiter
|
|
99
|
+
mockQuoteGet.mockResolvedValue({ route: "mock-route" });
|
|
100
|
+
// Mock a successful swap transaction response from Jupiter
|
|
101
|
+
mockSwapPost.mockResolvedValue({
|
|
102
|
+
swapTransaction: Buffer.from("mock-transaction").toString("base64"),
|
|
103
|
+
});
|
|
104
|
+
// Call the swap function
|
|
105
|
+
const result = await actionProvider.swap(mockWallet, swapArgs);
|
|
106
|
+
// Verify that Jupiter was called with correct parameters
|
|
107
|
+
expect(mockQuoteGet).toHaveBeenCalledWith({
|
|
108
|
+
inputMint: INPUT_MINT,
|
|
109
|
+
outputMint: OUTPUT_MINT,
|
|
110
|
+
amount: swapArgs.amount * 10 ** DECIMALS, // Ensure correct decimal conversion
|
|
111
|
+
slippageBps: swapArgs.slippageBps,
|
|
112
|
+
});
|
|
113
|
+
expect(mockSwapPost).toHaveBeenCalled();
|
|
114
|
+
expect(mockWallet.waitForSignatureResult).toHaveBeenCalledWith(MOCK_SIGNATURE);
|
|
115
|
+
expect(result).toContain("Successfully swapped");
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* Test handling of errors when retrieving a swap quote
|
|
119
|
+
*/
|
|
120
|
+
it("should handle swap quote errors", async () => {
|
|
121
|
+
mockQuoteGet.mockRejectedValue(new Error("Quote error")); // Simulate an API failure
|
|
122
|
+
const result = await actionProvider.swap(mockWallet, swapArgs);
|
|
123
|
+
expect(result).toBe("Error swapping tokens: Error: Quote error");
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* Test handling of errors when posting a swap transaction
|
|
127
|
+
*/
|
|
128
|
+
it("should handle swap transaction errors", async () => {
|
|
129
|
+
mockQuoteGet.mockResolvedValue({ route: "mock-route" });
|
|
130
|
+
mockSwapPost.mockRejectedValue(new Error("Swap transaction error")); // Simulate a failure
|
|
131
|
+
const result = await actionProvider.swap(mockWallet, swapArgs);
|
|
132
|
+
expect(result).toBe("Error swapping tokens: Error: Swap transaction error");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe("supportsNetwork", () => {
|
|
136
|
+
test.each([
|
|
137
|
+
[{ protocolFamily: "svm", networkId: "solana-mainnet" }, true, "solana mainnet"],
|
|
138
|
+
[{ protocolFamily: "svm", networkId: "solana-devnet" }, false, "solana devnet"],
|
|
139
|
+
[{ protocolFamily: "evm", networkId: "ethereum-mainnet" }, false, "ethereum mainnet"],
|
|
140
|
+
[{ protocolFamily: "evm", networkId: "solana-mainnet" }, false, "wrong protocol family"],
|
|
141
|
+
[{ protocolFamily: "svm", networkId: "ethereum-mainnet" }, false, "wrong network id"],
|
|
142
|
+
])("should return %p for %s", (network, expected) => {
|
|
143
|
+
expect(actionProvider.supportsNetwork(network)).toBe(expected);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Schema for swapping tokens using Jupiter.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SwapTokenSchema: z.ZodObject<{
|
|
6
|
+
inputMint: z.ZodString;
|
|
7
|
+
outputMint: z.ZodString;
|
|
8
|
+
amount: z.ZodNumber;
|
|
9
|
+
slippageBps: z.ZodDefault<z.ZodNumber>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
amount: number;
|
|
12
|
+
inputMint: string;
|
|
13
|
+
outputMint: string;
|
|
14
|
+
slippageBps: number;
|
|
15
|
+
}, {
|
|
16
|
+
amount: number;
|
|
17
|
+
inputMint: string;
|
|
18
|
+
outputMint: string;
|
|
19
|
+
slippageBps?: number | undefined;
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SwapTokenSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* Schema for swapping tokens using Jupiter.
|
|
7
|
+
*/
|
|
8
|
+
exports.SwapTokenSchema = zod_1.z
|
|
9
|
+
.object({
|
|
10
|
+
inputMint: zod_1.z.string().describe("The mint address of the token to swap from"),
|
|
11
|
+
outputMint: zod_1.z.string().describe("The mint address of the token to swap to"),
|
|
12
|
+
amount: zod_1.z.number().positive().describe("Amount of tokens to swap"),
|
|
13
|
+
slippageBps: zod_1.z
|
|
14
|
+
.number()
|
|
15
|
+
.int()
|
|
16
|
+
.positive()
|
|
17
|
+
.default(50)
|
|
18
|
+
.describe("Slippage tolerance in basis points (e.g., 50 = 0.5%)"),
|
|
19
|
+
})
|
|
20
|
+
.describe("Swap tokens using Jupiter DEX aggregator");
|
|
@@ -36,22 +36,29 @@ class SplActionProvider extends actionProvider_1.ActionProvider {
|
|
|
36
36
|
*/
|
|
37
37
|
async getBalance(walletProvider, args) {
|
|
38
38
|
try {
|
|
39
|
+
if (!args.address) {
|
|
40
|
+
args.address = walletProvider.getAddress();
|
|
41
|
+
}
|
|
39
42
|
const connection = walletProvider.getConnection();
|
|
40
43
|
const mintPubkey = new web3_js_1.PublicKey(args.mintAddress);
|
|
41
|
-
const ownerPubkey = args.address
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const ownerPubkey = new web3_js_1.PublicKey(args.address);
|
|
45
|
+
const { getMint, getAssociatedTokenAddress, getAccount, TokenAccountNotFoundError } = await import("@solana/spl-token");
|
|
46
|
+
let mintInfo;
|
|
47
|
+
try {
|
|
48
|
+
mintInfo = await getMint(connection, mintPubkey);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return `Failed to fetch mint info for mint address ${args.mintAddress}. Error: ${error}`;
|
|
52
|
+
}
|
|
47
53
|
try {
|
|
54
|
+
const ata = await getAssociatedTokenAddress(mintPubkey, ownerPubkey);
|
|
48
55
|
const account = await getAccount(connection, ata);
|
|
49
56
|
const balance = Number(account.amount) / Math.pow(10, mintInfo.decimals);
|
|
50
|
-
return `Balance for ${args.address
|
|
57
|
+
return `Balance for ${args.address} is ${balance} tokens`;
|
|
51
58
|
}
|
|
52
59
|
catch (error) {
|
|
53
|
-
if (error
|
|
54
|
-
return `Balance for ${args.address
|
|
60
|
+
if (error instanceof TokenAccountNotFoundError) {
|
|
61
|
+
return `Balance for ${args.address} is 0 tokens`;
|
|
55
62
|
}
|
|
56
63
|
throw error;
|
|
57
64
|
}
|
|
@@ -74,7 +81,13 @@ class SplActionProvider extends actionProvider_1.ActionProvider {
|
|
|
74
81
|
const toPubkey = new web3_js_1.PublicKey(args.recipient);
|
|
75
82
|
const mintPubkey = new web3_js_1.PublicKey(args.mintAddress);
|
|
76
83
|
const { getMint, getAssociatedTokenAddress, getAccount, createAssociatedTokenAccountInstruction, createTransferCheckedInstruction, } = await import("@solana/spl-token");
|
|
77
|
-
|
|
84
|
+
let mintInfo;
|
|
85
|
+
try {
|
|
86
|
+
mintInfo = await getMint(connection, mintPubkey);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
return `Failed to fetch mint info for mint address ${args.mintAddress}. Error: ${error}`;
|
|
90
|
+
}
|
|
78
91
|
const adjustedAmount = args.amount * Math.pow(10, mintInfo.decimals);
|
|
79
92
|
const sourceAta = await getAssociatedTokenAddress(mintPubkey, fromPubkey);
|
|
80
93
|
const destinationAta = await getAssociatedTokenAddress(mintPubkey, toPubkey);
|
|
@@ -16,13 +16,30 @@ jest.mock("@solana/web3.js", () => ({
|
|
|
16
16
|
compile: jest.fn().mockReturnValue({}),
|
|
17
17
|
},
|
|
18
18
|
}));
|
|
19
|
-
jest.mock("@solana/spl-token", () =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
jest.mock("@solana/spl-token", () => {
|
|
20
|
+
/**
|
|
21
|
+
* Custom error class for token account not found scenarios.
|
|
22
|
+
* Used to simulate cases where a token account doesn't exist.
|
|
23
|
+
*/
|
|
24
|
+
class TokenAccountNotFoundError extends Error {
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new TokenAccountNotFoundError instance.
|
|
27
|
+
* Sets the error message and name to identify token account not found scenarios.
|
|
28
|
+
*/
|
|
29
|
+
constructor() {
|
|
30
|
+
super("Token account not found");
|
|
31
|
+
this.name = "TokenAccountNotFoundError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
getAssociatedTokenAddress: jest.fn(),
|
|
36
|
+
getMint: jest.fn(),
|
|
37
|
+
getAccount: jest.fn(),
|
|
38
|
+
createAssociatedTokenAccountInstruction: jest.fn(),
|
|
39
|
+
createTransferCheckedInstruction: jest.fn(),
|
|
40
|
+
TokenAccountNotFoundError,
|
|
41
|
+
};
|
|
42
|
+
});
|
|
26
43
|
jest.mock("../../wallet-providers/svmWalletProvider");
|
|
27
44
|
describe("SplActionProvider", () => {
|
|
28
45
|
let actionProvider;
|
|
@@ -203,6 +220,9 @@ describe("SplActionProvider", () => {
|
|
|
203
220
|
expect(result).toContain(`Successfully transferred ${transferArgs.amount} tokens`);
|
|
204
221
|
});
|
|
205
222
|
});
|
|
223
|
+
/**
|
|
224
|
+
* Tests for the getBalance method
|
|
225
|
+
*/
|
|
206
226
|
describe("getBalance", () => {
|
|
207
227
|
const MINT_ADDRESS = "So11111111111111111111111111111111111111112";
|
|
208
228
|
const TARGET_ADDRESS = "DjXsn34uz8yCBQ8bevLrEPYYC1RvhHvjzuVF8opNc4K2";
|
|
@@ -232,14 +252,22 @@ describe("SplActionProvider", () => {
|
|
|
232
252
|
mockWallet.getPublicKey.mockReturnValue(new web3_js_1.PublicKey(SENDER_ADDRESS));
|
|
233
253
|
mockWallet.getAddress.mockReturnValue(SENDER_ADDRESS);
|
|
234
254
|
});
|
|
255
|
+
/**
|
|
256
|
+
* Tests that getBalance returns the correct balance for the connected wallet
|
|
257
|
+
* when no specific address is provided.
|
|
258
|
+
*/
|
|
235
259
|
it("should get balance for connected wallet", async () => {
|
|
236
260
|
mockGetAccount.mockResolvedValue(mockTokenAccount);
|
|
237
261
|
const result = await actionProvider.getBalance(mockWallet, balanceArgs);
|
|
238
262
|
expect(mockGetAssociatedTokenAddress).toHaveBeenCalledWith(new web3_js_1.PublicKey(balanceArgs.mintAddress), new web3_js_1.PublicKey(SENDER_ADDRESS));
|
|
239
263
|
expect(mockGetMint).toHaveBeenCalledWith(mockConnection, new web3_js_1.PublicKey(balanceArgs.mintAddress));
|
|
240
264
|
expect(mockGetAccount).toHaveBeenCalled();
|
|
241
|
-
expect(result).toBe(
|
|
265
|
+
expect(result).toBe(`Balance for ${SENDER_ADDRESS} is 1000 tokens`);
|
|
242
266
|
});
|
|
267
|
+
/**
|
|
268
|
+
* Tests that getBalance returns the correct balance when a specific
|
|
269
|
+
* address is provided in the arguments.
|
|
270
|
+
*/
|
|
243
271
|
it("should get balance for specified address", async () => {
|
|
244
272
|
mockGetAccount.mockResolvedValue(mockTokenAccount);
|
|
245
273
|
const result = await actionProvider.getBalance(mockWallet, balanceWithAddressArgs);
|
|
@@ -248,11 +276,20 @@ describe("SplActionProvider", () => {
|
|
|
248
276
|
expect(mockGetAccount).toHaveBeenCalled();
|
|
249
277
|
expect(result).toBe(`Balance for ${TARGET_ADDRESS} is 1000 tokens`);
|
|
250
278
|
});
|
|
279
|
+
/**
|
|
280
|
+
* Tests that getBalance correctly handles the case where a token account
|
|
281
|
+
* does not exist, returning a zero balance instead of an error.
|
|
282
|
+
*/
|
|
251
283
|
it("should handle non-existent token account", async () => {
|
|
252
|
-
|
|
284
|
+
const { TokenAccountNotFoundError } = jest.requireMock("@solana/spl-token");
|
|
285
|
+
mockGetAccount.mockRejectedValue(new TokenAccountNotFoundError());
|
|
253
286
|
const result = await actionProvider.getBalance(mockWallet, balanceArgs);
|
|
254
|
-
expect(result).toBe(
|
|
287
|
+
expect(result).toBe(`Balance for ${SENDER_ADDRESS} is 0 tokens`);
|
|
255
288
|
});
|
|
289
|
+
/**
|
|
290
|
+
* Tests that getBalance properly handles and reports unexpected errors
|
|
291
|
+
* that occur during the balance check.
|
|
292
|
+
*/
|
|
256
293
|
it("should handle errors", async () => {
|
|
257
294
|
const error = new Error("Test error");
|
|
258
295
|
mockGetAccount.mockRejectedValue(error);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GENERIC_TOKEN_METADATA_URI = exports.ADDRESSES = exports.WOW_FACTORY_CONTRACT_ADDRESSES = exports.WOW_ABI = exports.WOW_FACTORY_ABI = exports.SUPPORTED_NETWORKS = void 0;
|
|
4
4
|
exports.getFactoryAddress = getFactoryAddress;
|
|
5
|
-
exports.SUPPORTED_NETWORKS = ["base-mainnet"];
|
|
5
|
+
exports.SUPPORTED_NETWORKS = ["base-mainnet", "base-sepolia"];
|
|
6
6
|
exports.WOW_FACTORY_ABI = [
|
|
7
7
|
{
|
|
8
8
|
type: "constructor",
|
|
@@ -14,11 +14,11 @@ export declare class WowActionProvider extends ActionProvider<EvmWalletProvider>
|
|
|
14
14
|
/**
|
|
15
15
|
* Buys a Zora Wow ERC20 memecoin with ETH.
|
|
16
16
|
*
|
|
17
|
-
* @param
|
|
17
|
+
* @param walletProvider - The wallet to create the token from.
|
|
18
18
|
* @param args - The input arguments for the action.
|
|
19
19
|
* @returns A message containing the token purchase details.
|
|
20
20
|
*/
|
|
21
|
-
buyToken(
|
|
21
|
+
buyToken(walletProvider: EvmWalletProvider, args: z.infer<typeof WowBuyTokenInput>): Promise<string>;
|
|
22
22
|
/**
|
|
23
23
|
* Creates a Zora Wow ERC20 memecoin.
|
|
24
24
|
*
|
|
@@ -30,11 +30,11 @@ export declare class WowActionProvider extends ActionProvider<EvmWalletProvider>
|
|
|
30
30
|
/**
|
|
31
31
|
* Sells WOW tokens for ETH.
|
|
32
32
|
*
|
|
33
|
-
* @param
|
|
33
|
+
* @param walletProvider - The wallet to sell the tokens from.
|
|
34
34
|
* @param args - The input arguments for the action.
|
|
35
35
|
* @returns A message confirming the sale with the transaction hash.
|
|
36
36
|
*/
|
|
37
|
-
sellToken(
|
|
37
|
+
sellToken(walletProvider: EvmWalletProvider, args: z.infer<typeof WowSellTokenInput>): Promise<string>;
|
|
38
38
|
/**
|
|
39
39
|
* Checks if the Wow action provider supports the given network.
|
|
40
40
|
*
|
|
@@ -39,22 +39,22 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
39
39
|
/**
|
|
40
40
|
* Buys a Zora Wow ERC20 memecoin with ETH.
|
|
41
41
|
*
|
|
42
|
-
* @param
|
|
42
|
+
* @param walletProvider - The wallet to create the token from.
|
|
43
43
|
* @param args - The input arguments for the action.
|
|
44
44
|
* @returns A message containing the token purchase details.
|
|
45
45
|
*/
|
|
46
|
-
async buyToken(
|
|
46
|
+
async buyToken(walletProvider, args) {
|
|
47
47
|
try {
|
|
48
|
-
const tokenQuote = await (0, utils_1.getBuyQuote)(
|
|
48
|
+
const tokenQuote = await (0, utils_1.getBuyQuote)(walletProvider, args.contractAddress, args.amountEthInWei);
|
|
49
49
|
// Multiply by 99/100 and floor to get 99% of quote as minimum
|
|
50
50
|
const minTokens = BigInt(Math.floor(Number(tokenQuote) * 99)) / BigInt(100);
|
|
51
|
-
const hasGraduated = await (0, utils_2.getHasGraduated)(
|
|
51
|
+
const hasGraduated = await (0, utils_2.getHasGraduated)(walletProvider, args.contractAddress);
|
|
52
52
|
const data = (0, viem_1.encodeFunctionData)({
|
|
53
53
|
abi: constants_1.WOW_ABI,
|
|
54
54
|
functionName: "buy",
|
|
55
55
|
args: [
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
walletProvider.getAddress(),
|
|
57
|
+
walletProvider.getAddress(),
|
|
58
58
|
"0x0000000000000000000000000000000000000000",
|
|
59
59
|
"",
|
|
60
60
|
hasGraduated ? 1n : 0n,
|
|
@@ -62,13 +62,13 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
62
62
|
0n,
|
|
63
63
|
],
|
|
64
64
|
});
|
|
65
|
-
const txHash = await
|
|
65
|
+
const txHash = await walletProvider.sendTransaction({
|
|
66
66
|
to: args.contractAddress,
|
|
67
67
|
data,
|
|
68
68
|
value: BigInt(args.amountEthInWei),
|
|
69
69
|
});
|
|
70
|
-
|
|
71
|
-
return `Purchased WoW ERC20 memecoin with transaction hash: ${txHash}
|
|
70
|
+
await walletProvider.waitForTransactionReceipt(txHash);
|
|
71
|
+
return `Purchased WoW ERC20 memecoin with transaction hash: ${txHash}`;
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
74
74
|
return `Error buying Zora Wow ERC20 memecoin: ${error}`;
|
|
@@ -99,8 +99,8 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
99
99
|
to: factoryAddress,
|
|
100
100
|
data,
|
|
101
101
|
});
|
|
102
|
-
|
|
103
|
-
return `Created WoW ERC20 memecoin ${args.name} with symbol ${args.symbol} on network ${wallet.getNetwork().networkId}.\nTransaction hash
|
|
102
|
+
await wallet.waitForTransactionReceipt(txHash);
|
|
103
|
+
return `Created WoW ERC20 memecoin ${args.name} with symbol ${args.symbol} on network ${wallet.getNetwork().networkId}.\nTransaction hash: ${txHash}`;
|
|
104
104
|
}
|
|
105
105
|
catch (error) {
|
|
106
106
|
return `Error creating Zora Wow ERC20 memecoin: ${error}`;
|
|
@@ -109,14 +109,14 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
109
109
|
/**
|
|
110
110
|
* Sells WOW tokens for ETH.
|
|
111
111
|
*
|
|
112
|
-
* @param
|
|
112
|
+
* @param walletProvider - The wallet to sell the tokens from.
|
|
113
113
|
* @param args - The input arguments for the action.
|
|
114
114
|
* @returns A message confirming the sale with the transaction hash.
|
|
115
115
|
*/
|
|
116
|
-
async sellToken(
|
|
116
|
+
async sellToken(walletProvider, args) {
|
|
117
117
|
try {
|
|
118
|
-
const ethQuote = await (0, utils_1.getSellQuote)(
|
|
119
|
-
const hasGraduated = await (0, utils_2.getHasGraduated)(
|
|
118
|
+
const ethQuote = await (0, utils_1.getSellQuote)(walletProvider, args.contractAddress, args.amountTokensInWei);
|
|
119
|
+
const hasGraduated = await (0, utils_2.getHasGraduated)(walletProvider, args.contractAddress);
|
|
120
120
|
// Multiply by 98/100 and floor to get 98% of quote as minimum
|
|
121
121
|
const minEth = BigInt(Math.floor(Number(ethQuote) * 98)) / BigInt(100);
|
|
122
122
|
const data = (0, viem_1.encodeFunctionData)({
|
|
@@ -124,7 +124,7 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
124
124
|
functionName: "sell",
|
|
125
125
|
args: [
|
|
126
126
|
BigInt(args.amountTokensInWei),
|
|
127
|
-
|
|
127
|
+
walletProvider.getAddress(),
|
|
128
128
|
"0x0000000000000000000000000000000000000000",
|
|
129
129
|
"",
|
|
130
130
|
hasGraduated ? 1n : 0n,
|
|
@@ -132,12 +132,12 @@ class WowActionProvider extends actionProvider_1.ActionProvider {
|
|
|
132
132
|
0n,
|
|
133
133
|
],
|
|
134
134
|
});
|
|
135
|
-
const txHash = await
|
|
135
|
+
const txHash = await walletProvider.sendTransaction({
|
|
136
136
|
to: args.contractAddress,
|
|
137
137
|
data,
|
|
138
138
|
});
|
|
139
|
-
|
|
140
|
-
return `Sold WoW ERC20 memecoin with transaction hash: ${txHash}
|
|
139
|
+
await walletProvider.waitForTransactionReceipt(txHash);
|
|
140
|
+
return `Sold WoW ERC20 memecoin with transaction hash: ${txHash}`;
|
|
141
141
|
}
|
|
142
142
|
catch (error) {
|
|
143
143
|
return `Error selling Zora Wow ERC20 memecoin: ${error}`;
|
|
@@ -142,13 +142,17 @@ describe("WowActionProvider", () => {
|
|
|
142
142
|
});
|
|
143
143
|
});
|
|
144
144
|
describe("supportsNetwork", () => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
const testCases = [
|
|
146
|
+
{ network: { protocolFamily: "evm", networkId: "base-mainnet" }, expected: true },
|
|
147
|
+
{ network: { protocolFamily: "evm", networkId: "base-sepolia" }, expected: true },
|
|
148
|
+
{ network: { protocolFamily: "evm", networkId: "ethereum" }, expected: false },
|
|
149
|
+
{ network: { protocolFamily: "evm", networkId: "optimism" }, expected: false },
|
|
150
|
+
{ network: { protocolFamily: "bitcoin", networkId: "base-mainnet" }, expected: false },
|
|
151
|
+
];
|
|
152
|
+
testCases.forEach(({ network, expected }) => {
|
|
153
|
+
it(`should ${expected ? "support" : "not support"} ${network.protocolFamily}/${network.networkId}`, () => {
|
|
154
|
+
expect(provider.supportsNetwork(network)).toBe(expected);
|
|
155
|
+
});
|
|
152
156
|
});
|
|
153
157
|
});
|
|
154
158
|
describe("buyToken", () => {
|
|
@@ -186,7 +190,7 @@ describe("WowActionProvider", () => {
|
|
|
186
190
|
const error = new Error("Buy failed");
|
|
187
191
|
mockWallet.sendTransaction.mockRejectedValue(error);
|
|
188
192
|
const response = await provider.buyToken(mockWallet, args);
|
|
189
|
-
expect(response).
|
|
193
|
+
expect(response).toBe(`Error buying Zora Wow ERC20 memecoin: ${error}`);
|
|
190
194
|
});
|
|
191
195
|
});
|
|
192
196
|
describe("createToken", () => {
|
|
@@ -244,7 +248,7 @@ describe("WowActionProvider", () => {
|
|
|
244
248
|
const error = new Error("Create failed");
|
|
245
249
|
mockWallet.sendTransaction.mockRejectedValue(error);
|
|
246
250
|
const response = await provider.createToken(mockWallet, args);
|
|
247
|
-
expect(response).
|
|
251
|
+
expect(response).toBe(`Error creating Zora Wow ERC20 memecoin: ${error}`);
|
|
248
252
|
});
|
|
249
253
|
});
|
|
250
254
|
describe("sellToken", () => {
|
|
@@ -281,7 +285,7 @@ describe("WowActionProvider", () => {
|
|
|
281
285
|
const error = new Error("Sell failed");
|
|
282
286
|
mockWallet.sendTransaction.mockRejectedValue(error);
|
|
283
287
|
const response = await provider.sellToken(mockWallet, args);
|
|
284
|
-
expect(response).
|
|
288
|
+
expect(response).toBe(`Error selling Zora Wow ERC20 memecoin: ${error}`);
|
|
285
289
|
});
|
|
286
290
|
});
|
|
287
291
|
});
|
package/dist/agentkit.js
CHANGED
|
@@ -49,10 +49,18 @@ class AgentKit {
|
|
|
49
49
|
*/
|
|
50
50
|
getActions() {
|
|
51
51
|
const actions = [];
|
|
52
|
+
const unsupported = [];
|
|
52
53
|
for (const actionProvider of this.actionProviders) {
|
|
53
54
|
if (actionProvider.supportsNetwork(this.walletProvider.getNetwork())) {
|
|
54
55
|
actions.push(...actionProvider.getActions(this.walletProvider));
|
|
55
56
|
}
|
|
57
|
+
else {
|
|
58
|
+
unsupported.push(actionProvider.name);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (unsupported.length > 0) {
|
|
62
|
+
console.log(`Warning: The following action providers are not supported on the current network and will be unavailable: ${unsupported.join(", ")}`);
|
|
63
|
+
console.log("Current network:", this.walletProvider.getNetwork());
|
|
56
64
|
}
|
|
57
65
|
return actions;
|
|
58
66
|
}
|
|
@@ -58,7 +58,7 @@ class CdpWalletProvider extends evmWalletProvider_1.EvmWalletProvider {
|
|
|
58
58
|
if (config.apiKeyName && config.apiKeyPrivateKey) {
|
|
59
59
|
coinbase_sdk_1.Coinbase.configure({
|
|
60
60
|
apiKeyName: config.apiKeyName,
|
|
61
|
-
privateKey: config.apiKeyPrivateKey,
|
|
61
|
+
privateKey: config.apiKeyPrivateKey?.replace(/\\n/g, "\n"),
|
|
62
62
|
source: "agentkit",
|
|
63
63
|
sourceVersion: package_json_1.version,
|
|
64
64
|
});
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@coinbase/agentkit",
|
|
3
3
|
"description": "Coinbase AgentKit core primitives",
|
|
4
4
|
"repository": "https://github.com/coinbase/agentkit",
|
|
5
|
-
"version": "0.2.1",
|
|
5
|
+
"version": "0.2.2-nightly.20250221.1",
|
|
6
6
|
"author": "Coinbase Inc.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"main": "dist/index.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@coinbase/coinbase-sdk": "^0.17.0",
|
|
43
|
+
"@jup-ag/api": "^6.0.39",
|
|
43
44
|
"@privy-io/server-auth": "^1.18.4",
|
|
44
45
|
"@solana/spl-token": "^0.4.12",
|
|
45
46
|
"@solana/web3.js": "^1.98.0",
|