@coinbase/agentkit 0.0.0-nightly-20250328174338 → 0.0.0-nightly-20250328210410
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 +51 -7
- package/dist/wallet-providers/index.d.ts +1 -0
- package/dist/wallet-providers/index.js +1 -0
- package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.d.ts +167 -0
- package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.js +438 -0
- package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.test.js +280 -0
- package/dist/wallet-providers/privyShared.d.ts +9 -0
- package/dist/wallet-providers/privyShared.js +16 -5
- package/dist/wallet-providers/privyWalletProvider.d.ts +21 -8
- package/dist/wallet-providers/privyWalletProvider.js +39 -7
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -646,24 +646,61 @@ const walletProvider = new ViemWalletProvider(client, {
|
|
|
646
646
|
|
|
647
647
|
### PrivyWalletProvider
|
|
648
648
|
|
|
649
|
-
The `PrivyWalletProvider` is a wallet provider that uses [Privy Server Wallets](https://docs.privy.io/guide/server-wallets/). This implementation extends the `
|
|
649
|
+
The `PrivyWalletProvider` is a wallet provider that uses [Privy Server Wallets](https://docs.privy.io/guide/server-wallets/) or [Privy Embedded Wallets](https://docs.privy.io/guide/embedded-wallets/). This implementation extends the `EvmWalletProvider`.
|
|
650
|
+
|
|
651
|
+
#### Server Wallet Configuration
|
|
650
652
|
|
|
651
653
|
```typescript
|
|
652
|
-
import { PrivyWalletProvider
|
|
654
|
+
import { PrivyWalletProvider } from "@coinbase/agentkit";
|
|
653
655
|
|
|
654
|
-
// Configure Wallet Provider
|
|
655
|
-
const config
|
|
656
|
+
// Configure Server Wallet Provider
|
|
657
|
+
const config = {
|
|
656
658
|
appId: "PRIVY_APP_ID",
|
|
657
659
|
appSecret: "PRIVY_APP_SECRET",
|
|
658
660
|
chainId: "84532", // base-sepolia
|
|
659
661
|
walletId: "PRIVY_WALLET_ID", // optional, otherwise a new wallet will be created
|
|
660
|
-
authorizationPrivateKey: PRIVY_WALLET_AUTHORIZATION_PRIVATE_KEY, // optional, required if your account is using authorization keys
|
|
661
|
-
authorizationKeyId: PRIVY_WALLET_AUTHORIZATION_KEY_ID, // optional, only required to create a new wallet if walletId is not provided
|
|
662
|
+
authorizationPrivateKey: "PRIVY_WALLET_AUTHORIZATION_PRIVATE_KEY", // optional, required if your account is using authorization keys
|
|
663
|
+
authorizationKeyId: "PRIVY_WALLET_AUTHORIZATION_KEY_ID", // optional, only required to create a new wallet if walletId is not provided
|
|
662
664
|
};
|
|
663
665
|
|
|
664
666
|
const walletProvider = await PrivyWalletProvider.configureWithWallet(config);
|
|
665
667
|
```
|
|
666
668
|
|
|
669
|
+
#### Delegated Embedded Wallet Configuration
|
|
670
|
+
|
|
671
|
+
You can also use Privy's embedded wallets with delegation for agent actions. This allows your agent to use wallets that have been delegated transaction signing authority by users.
|
|
672
|
+
|
|
673
|
+
```typescript
|
|
674
|
+
import { PrivyWalletProvider } from "@coinbase/agentkit";
|
|
675
|
+
|
|
676
|
+
// Configure Embedded Wallet Provider
|
|
677
|
+
const config = {
|
|
678
|
+
appId: "PRIVY_APP_ID",
|
|
679
|
+
appSecret: "PRIVY_APP_SECRET",
|
|
680
|
+
authorizationPrivateKey: "PRIVY_WALLET_AUTHORIZATION_PRIVATE_KEY",
|
|
681
|
+
walletId: "PRIVY_DELEGATED_WALLET_ID", // The ID of the wallet that was delegated to your server
|
|
682
|
+
networkId: "base-mainnet", // or any supported network
|
|
683
|
+
walletType: "embedded" // Specify "embedded" to use the embedded wallet provider
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
const walletProvider = await PrivyWalletProvider.configureWithWallet(config);
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### Prerequisites
|
|
690
|
+
|
|
691
|
+
Before using this wallet provider, you need to:
|
|
692
|
+
|
|
693
|
+
1. Set up Privy in your application
|
|
694
|
+
2. Enable server delegated actions
|
|
695
|
+
3. Have users delegate permissions to your server
|
|
696
|
+
4. Obtain the delegated wallet ID
|
|
697
|
+
|
|
698
|
+
For more information on setting up Privy and enabling delegated actions, see [Privy's documentation](https://docs.privy.io/guide/embedded/server-delegated-actions).
|
|
699
|
+
|
|
700
|
+
### Supported Operations
|
|
701
|
+
|
|
702
|
+
The `PrivyEvmDelegatedEmbeddedWalletProvider` supports all standard wallet operations including transaction signing, message signing, and native transfers, using the wallet that was delegated to your server.
|
|
703
|
+
|
|
667
704
|
#### Authorization Keys
|
|
668
705
|
|
|
669
706
|
Privy offers the option to use authorization keys to secure your server wallets.
|
|
@@ -679,12 +716,19 @@ The `PrivyWalletProvider` can export wallet information by calling the `exportWa
|
|
|
679
716
|
```typescript
|
|
680
717
|
const walletData = await walletProvider.exportWallet();
|
|
681
718
|
|
|
682
|
-
// walletData will be in the following format:
|
|
719
|
+
// For server wallets, walletData will be in the following format:
|
|
683
720
|
{
|
|
684
721
|
walletId: string;
|
|
685
722
|
authorizationKey: string | undefined;
|
|
686
723
|
chainId: string | undefined;
|
|
687
724
|
}
|
|
725
|
+
|
|
726
|
+
// For embedded wallets, walletData will be in the following format:
|
|
727
|
+
{
|
|
728
|
+
walletId: string;
|
|
729
|
+
networkId: string;
|
|
730
|
+
chainId: string | undefined;
|
|
731
|
+
}
|
|
688
732
|
```
|
|
689
733
|
|
|
690
734
|
### SmartWalletProvider
|
|
@@ -24,3 +24,4 @@ __exportStar(require("./solanaKeypairWalletProvider"), exports);
|
|
|
24
24
|
__exportStar(require("./privyWalletProvider"), exports);
|
|
25
25
|
__exportStar(require("./privyEvmWalletProvider"), exports);
|
|
26
26
|
__exportStar(require("./privySvmWalletProvider"), exports);
|
|
27
|
+
__exportStar(require("./privyEvmDelegatedEmbeddedWalletProvider"), exports);
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Abi, ContractFunctionArgs, ContractFunctionName, Hex, ReadContractParameters, ReadContractReturnType, TransactionReceipt, TransactionRequest } from "viem";
|
|
2
|
+
import { Network } from "../network";
|
|
3
|
+
import { PrivyWalletConfig, PrivyWalletExport } from "./privyShared";
|
|
4
|
+
import { WalletProvider } from "./walletProvider";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the Privy Embedded Wallet provider.
|
|
7
|
+
*/
|
|
8
|
+
export interface PrivyEvmDelegatedEmbeddedWalletConfig extends PrivyWalletConfig {
|
|
9
|
+
/** The ID of the delegated wallet */
|
|
10
|
+
walletId: string;
|
|
11
|
+
/** The network ID to connect to (e.g., "base-mainnet") */
|
|
12
|
+
networkId?: string;
|
|
13
|
+
/** The chain ID to connect to */
|
|
14
|
+
chainId?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A wallet provider that uses Privy's embedded wallets with delegation.
|
|
18
|
+
* This provider extends the EvmWalletProvider to provide Privy-specific wallet functionality
|
|
19
|
+
* while maintaining compatibility with the base wallet provider interface.
|
|
20
|
+
*/
|
|
21
|
+
export declare class PrivyEvmDelegatedEmbeddedWalletProvider extends WalletProvider {
|
|
22
|
+
#private;
|
|
23
|
+
/**
|
|
24
|
+
* Private constructor to enforce use of factory method.
|
|
25
|
+
*
|
|
26
|
+
* @param config - The configuration options for the wallet provider
|
|
27
|
+
*/
|
|
28
|
+
private constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Creates and configures a new PrivyEvmDelegatedEmbeddedWalletProvider instance.
|
|
31
|
+
*
|
|
32
|
+
* @param config - The configuration options for the Privy wallet
|
|
33
|
+
* @returns A configured PrivyEvmDelegatedEmbeddedWalletProvider instance
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const provider = await PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet({
|
|
38
|
+
* appId: "your-app-id",
|
|
39
|
+
* appSecret: "your-app-secret",
|
|
40
|
+
* authorizationPrivateKey: "your-auth-key",
|
|
41
|
+
* walletId: "privy-wallet-id",
|
|
42
|
+
* networkId: "base-mainnet"
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
static configureWithWallet(config: PrivyEvmDelegatedEmbeddedWalletConfig): Promise<PrivyEvmDelegatedEmbeddedWalletProvider>;
|
|
47
|
+
/**
|
|
48
|
+
* Gets the address of the wallet.
|
|
49
|
+
*
|
|
50
|
+
* @returns The address of the wallet.
|
|
51
|
+
*/
|
|
52
|
+
getAddress(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the network of the wallet.
|
|
55
|
+
*
|
|
56
|
+
* @returns The network of the wallet.
|
|
57
|
+
*/
|
|
58
|
+
getNetwork(): Network;
|
|
59
|
+
/**
|
|
60
|
+
* Gets the name of the wallet provider.
|
|
61
|
+
*
|
|
62
|
+
* @returns The name of the wallet provider.
|
|
63
|
+
*/
|
|
64
|
+
getName(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Gets the balance of the wallet.
|
|
67
|
+
*
|
|
68
|
+
* @returns The balance of the wallet in wei
|
|
69
|
+
*/
|
|
70
|
+
getBalance(): Promise<bigint>;
|
|
71
|
+
/**
|
|
72
|
+
* Signs a message.
|
|
73
|
+
*
|
|
74
|
+
* @param message - The message to sign.
|
|
75
|
+
* @returns The signed message.
|
|
76
|
+
*/
|
|
77
|
+
signMessage(message: string): Promise<Hex>;
|
|
78
|
+
/**
|
|
79
|
+
* Signs typed data according to EIP-712.
|
|
80
|
+
*
|
|
81
|
+
* @param typedData - The typed data object to sign
|
|
82
|
+
* @param typedData.domain - The domain object containing contract and chain information
|
|
83
|
+
* @param typedData.types - The type definitions for the structured data
|
|
84
|
+
* @param typedData.primaryType - The primary type being signed
|
|
85
|
+
* @param typedData.message - The actual data to sign
|
|
86
|
+
* @returns A Address that resolves to the signed typed data as a hex string
|
|
87
|
+
*/
|
|
88
|
+
signTypedData(typedData: {
|
|
89
|
+
domain: Record<string, unknown>;
|
|
90
|
+
types: Record<string, Array<{
|
|
91
|
+
name: string;
|
|
92
|
+
type: string;
|
|
93
|
+
}>>;
|
|
94
|
+
primaryType: string;
|
|
95
|
+
message: Record<string, unknown>;
|
|
96
|
+
}): Promise<Hex>;
|
|
97
|
+
/**
|
|
98
|
+
* Signs a transaction.
|
|
99
|
+
*
|
|
100
|
+
* @param transaction - The transaction to sign.
|
|
101
|
+
* @returns The signed transaction.
|
|
102
|
+
*/
|
|
103
|
+
signTransaction(transaction: TransactionRequest): Promise<Hex>;
|
|
104
|
+
/**
|
|
105
|
+
* Sends a transaction.
|
|
106
|
+
*
|
|
107
|
+
* @param transaction - The transaction to send.
|
|
108
|
+
* @returns The hash of the transaction.
|
|
109
|
+
*/
|
|
110
|
+
sendTransaction(transaction: TransactionRequest): Promise<Hex>;
|
|
111
|
+
/**
|
|
112
|
+
* Waits for a transaction receipt.
|
|
113
|
+
*
|
|
114
|
+
* @param txHash - The hash of the transaction to wait for.
|
|
115
|
+
* @returns The transaction receipt.
|
|
116
|
+
*/
|
|
117
|
+
waitForTransactionReceipt(txHash: Hex): Promise<TransactionReceipt>;
|
|
118
|
+
/**
|
|
119
|
+
* Reads data from a smart contract.
|
|
120
|
+
*
|
|
121
|
+
* @param params - Parameters for reading the contract
|
|
122
|
+
* @param params.address - The address of the contract
|
|
123
|
+
* @param params.abi - The ABI of the contract
|
|
124
|
+
* @param params.functionName - The name of the function to call
|
|
125
|
+
* @param params.args - The arguments to pass to the function
|
|
126
|
+
* @returns A Address that resolves to the contract function's return value
|
|
127
|
+
*/
|
|
128
|
+
readContract<const abi extends Abi | readonly unknown[], functionName extends ContractFunctionName<abi, "pure" | "view">, const args extends ContractFunctionArgs<abi, "pure" | "view", functionName>>(params: ReadContractParameters<abi, functionName, args>): Promise<ReadContractReturnType<abi, functionName, args>>;
|
|
129
|
+
/**
|
|
130
|
+
* Transfer the native asset of the network.
|
|
131
|
+
*
|
|
132
|
+
* @param to - The destination address.
|
|
133
|
+
* @param value - The amount to transfer in Wei.
|
|
134
|
+
* @returns The transaction hash.
|
|
135
|
+
*/
|
|
136
|
+
nativeTransfer(to: string, value: string): Promise<Hex>;
|
|
137
|
+
/**
|
|
138
|
+
* Exports the wallet information.
|
|
139
|
+
*
|
|
140
|
+
* @returns The wallet data
|
|
141
|
+
*/
|
|
142
|
+
exportWallet(): PrivyWalletExport;
|
|
143
|
+
/**
|
|
144
|
+
* Generate Privy authorization signature for API requests
|
|
145
|
+
*
|
|
146
|
+
* @param url - The URL for the request
|
|
147
|
+
* @param body - The request body
|
|
148
|
+
* @returns The generated signature
|
|
149
|
+
*/
|
|
150
|
+
private generatePrivySignature;
|
|
151
|
+
/**
|
|
152
|
+
* Get Privy headers for API requests
|
|
153
|
+
*
|
|
154
|
+
* @param url - The URL for the request
|
|
155
|
+
* @param body - The request body
|
|
156
|
+
* @returns The headers for the request
|
|
157
|
+
*/
|
|
158
|
+
private getPrivyHeaders;
|
|
159
|
+
/**
|
|
160
|
+
* Execute a Privy API request.
|
|
161
|
+
*
|
|
162
|
+
* @param body - The request body to send to the Privy API
|
|
163
|
+
* @returns A promise that resolves to the response data
|
|
164
|
+
* @throws Error if the request fails
|
|
165
|
+
*/
|
|
166
|
+
private executePrivyRequest;
|
|
167
|
+
}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _PrivyEvmDelegatedEmbeddedWalletProvider_walletId, _PrivyEvmDelegatedEmbeddedWalletProvider_address, _PrivyEvmDelegatedEmbeddedWalletProvider_appId, _PrivyEvmDelegatedEmbeddedWalletProvider_appSecret, _PrivyEvmDelegatedEmbeddedWalletProvider_authKey, _PrivyEvmDelegatedEmbeddedWalletProvider_network, _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.PrivyEvmDelegatedEmbeddedWalletProvider = void 0;
|
|
19
|
+
const canonicalize_1 = __importDefault(require("canonicalize"));
|
|
20
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
21
|
+
const viem_1 = require("viem");
|
|
22
|
+
const network_1 = require("../network/network");
|
|
23
|
+
const privyShared_1 = require("./privyShared");
|
|
24
|
+
const walletProvider_1 = require("./walletProvider");
|
|
25
|
+
/**
|
|
26
|
+
* A wallet provider that uses Privy's embedded wallets with delegation.
|
|
27
|
+
* This provider extends the EvmWalletProvider to provide Privy-specific wallet functionality
|
|
28
|
+
* while maintaining compatibility with the base wallet provider interface.
|
|
29
|
+
*/
|
|
30
|
+
class PrivyEvmDelegatedEmbeddedWalletProvider extends walletProvider_1.WalletProvider {
|
|
31
|
+
/**
|
|
32
|
+
* Private constructor to enforce use of factory method.
|
|
33
|
+
*
|
|
34
|
+
* @param config - The configuration options for the wallet provider
|
|
35
|
+
*/
|
|
36
|
+
constructor(config) {
|
|
37
|
+
super();
|
|
38
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_walletId.set(this, void 0);
|
|
39
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_address.set(this, void 0);
|
|
40
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_appId.set(this, void 0);
|
|
41
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_appSecret.set(this, void 0);
|
|
42
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_authKey.set(this, void 0);
|
|
43
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_network.set(this, void 0);
|
|
44
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_publicClient.set(this, void 0);
|
|
45
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_walletId, config.walletId, "f");
|
|
46
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, config.address, "f");
|
|
47
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appId, config.appId, "f");
|
|
48
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appSecret, config.appSecret, "f");
|
|
49
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_authKey, config.authorizationPrivateKey || "", "f");
|
|
50
|
+
const networkId = config.networkId || "base-sepolia";
|
|
51
|
+
const chainId = config.chainId || network_1.NETWORK_ID_TO_CHAIN_ID[networkId];
|
|
52
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, {
|
|
53
|
+
protocolFamily: "evm",
|
|
54
|
+
networkId: networkId,
|
|
55
|
+
chainId: chainId,
|
|
56
|
+
}, "f");
|
|
57
|
+
// Create a public client for read operations
|
|
58
|
+
const chain = (0, network_1.getChain)(chainId);
|
|
59
|
+
if (!chain) {
|
|
60
|
+
throw new Error(`Chain with ID ${chainId} not found`);
|
|
61
|
+
}
|
|
62
|
+
__classPrivateFieldSet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient, (0, viem_1.createPublicClient)({
|
|
63
|
+
chain,
|
|
64
|
+
transport: (0, viem_1.http)(),
|
|
65
|
+
}), "f");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates and configures a new PrivyEvmDelegatedEmbeddedWalletProvider instance.
|
|
69
|
+
*
|
|
70
|
+
* @param config - The configuration options for the Privy wallet
|
|
71
|
+
* @returns A configured PrivyEvmDelegatedEmbeddedWalletProvider instance
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const provider = await PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet({
|
|
76
|
+
* appId: "your-app-id",
|
|
77
|
+
* appSecret: "your-app-secret",
|
|
78
|
+
* authorizationPrivateKey: "your-auth-key",
|
|
79
|
+
* walletId: "privy-wallet-id",
|
|
80
|
+
* networkId: "base-mainnet"
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
static async configureWithWallet(config) {
|
|
85
|
+
try {
|
|
86
|
+
if (!config.walletId) {
|
|
87
|
+
throw new Error("walletId is required for PrivyEvmDelegatedEmbeddedWalletProvider");
|
|
88
|
+
}
|
|
89
|
+
if (!config.appId || !config.appSecret) {
|
|
90
|
+
throw new Error("appId and appSecret are required for PrivyEvmDelegatedEmbeddedWalletProvider");
|
|
91
|
+
}
|
|
92
|
+
if (!config.authorizationPrivateKey) {
|
|
93
|
+
throw new Error("authorizationPrivateKey is required for PrivyEvmDelegatedEmbeddedWalletProvider");
|
|
94
|
+
}
|
|
95
|
+
const privyClient = (0, privyShared_1.createPrivyClient)(config);
|
|
96
|
+
const user = await privyClient.getUser(config.walletId);
|
|
97
|
+
const embeddedWallets = user.linkedAccounts.filter((account) => account.type === "wallet" && account.walletClientType === "privy");
|
|
98
|
+
if (embeddedWallets.length === 0) {
|
|
99
|
+
throw new Error(`Could not find wallet address for wallet ID ${config.walletId}`);
|
|
100
|
+
}
|
|
101
|
+
const walletAddress = embeddedWallets[0].address;
|
|
102
|
+
// Verify the network/chain ID if provided
|
|
103
|
+
if (config.chainId) {
|
|
104
|
+
const chain = (0, network_1.getChain)(config.chainId);
|
|
105
|
+
if (!chain) {
|
|
106
|
+
throw new Error(`Chain with ID ${config.chainId} not found`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return new PrivyEvmDelegatedEmbeddedWalletProvider({
|
|
110
|
+
...config,
|
|
111
|
+
address: walletAddress,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error instanceof Error) {
|
|
116
|
+
throw new Error(`Failed to configure Privy embedded wallet provider: ${error.message}`);
|
|
117
|
+
}
|
|
118
|
+
throw new Error("Failed to configure Privy embedded wallet provider");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Gets the address of the wallet.
|
|
123
|
+
*
|
|
124
|
+
* @returns The address of the wallet.
|
|
125
|
+
*/
|
|
126
|
+
getAddress() {
|
|
127
|
+
return __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Gets the network of the wallet.
|
|
131
|
+
*
|
|
132
|
+
* @returns The network of the wallet.
|
|
133
|
+
*/
|
|
134
|
+
getNetwork() {
|
|
135
|
+
return __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Gets the name of the wallet provider.
|
|
139
|
+
*
|
|
140
|
+
* @returns The name of the wallet provider.
|
|
141
|
+
*/
|
|
142
|
+
getName() {
|
|
143
|
+
return "privy_evm_embedded_wallet_provider";
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Gets the balance of the wallet.
|
|
147
|
+
*
|
|
148
|
+
* @returns The balance of the wallet in wei
|
|
149
|
+
*/
|
|
150
|
+
async getBalance() {
|
|
151
|
+
try {
|
|
152
|
+
const balance = await __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient, "f").getBalance({
|
|
153
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
154
|
+
});
|
|
155
|
+
return balance;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error instanceof Error) {
|
|
159
|
+
throw new Error(`Error getting balance: ${error.message}`);
|
|
160
|
+
}
|
|
161
|
+
throw new Error("Error getting balance");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Signs a message.
|
|
166
|
+
*
|
|
167
|
+
* @param message - The message to sign.
|
|
168
|
+
* @returns The signed message.
|
|
169
|
+
*/
|
|
170
|
+
async signMessage(message) {
|
|
171
|
+
const body = {
|
|
172
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
173
|
+
chain_type: "ethereum",
|
|
174
|
+
method: "personal_sign",
|
|
175
|
+
params: {
|
|
176
|
+
message,
|
|
177
|
+
encoding: "utf-8",
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
try {
|
|
181
|
+
const response = await this.executePrivyRequest(body);
|
|
182
|
+
return response.data?.signature;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error instanceof Error) {
|
|
186
|
+
throw new Error(`Message signing failed: ${error.message}`);
|
|
187
|
+
}
|
|
188
|
+
throw new Error("Message signing failed");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Signs typed data according to EIP-712.
|
|
193
|
+
*
|
|
194
|
+
* @param typedData - The typed data object to sign
|
|
195
|
+
* @param typedData.domain - The domain object containing contract and chain information
|
|
196
|
+
* @param typedData.types - The type definitions for the structured data
|
|
197
|
+
* @param typedData.primaryType - The primary type being signed
|
|
198
|
+
* @param typedData.message - The actual data to sign
|
|
199
|
+
* @returns A Address that resolves to the signed typed data as a hex string
|
|
200
|
+
*/
|
|
201
|
+
async signTypedData(typedData) {
|
|
202
|
+
const body = {
|
|
203
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
204
|
+
chain_type: "ethereum",
|
|
205
|
+
chain_id: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f").chainId,
|
|
206
|
+
...typedData,
|
|
207
|
+
};
|
|
208
|
+
try {
|
|
209
|
+
const response = await this.executePrivyRequest({
|
|
210
|
+
method: "eth_signTypedData_v4",
|
|
211
|
+
params: body,
|
|
212
|
+
});
|
|
213
|
+
return response.signature;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
if (error instanceof Error) {
|
|
217
|
+
throw new Error("Typed data signing failed: " + error.message);
|
|
218
|
+
}
|
|
219
|
+
throw new Error("Typed data signing failed with unknown error");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Signs a transaction.
|
|
224
|
+
*
|
|
225
|
+
* @param transaction - The transaction to sign.
|
|
226
|
+
* @returns The signed transaction.
|
|
227
|
+
*/
|
|
228
|
+
async signTransaction(transaction) {
|
|
229
|
+
const body = {
|
|
230
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
231
|
+
chain_type: "ethereum",
|
|
232
|
+
method: "eth_signTransaction",
|
|
233
|
+
params: {
|
|
234
|
+
transaction: {
|
|
235
|
+
...transaction,
|
|
236
|
+
from: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
try {
|
|
241
|
+
const response = await this.executePrivyRequest(body);
|
|
242
|
+
return response.data?.signed_transaction;
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
if (error instanceof Error) {
|
|
246
|
+
throw new Error(`Transaction signing failed: ${error.message}`);
|
|
247
|
+
}
|
|
248
|
+
throw new Error("Transaction signing failed");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Sends a transaction.
|
|
253
|
+
*
|
|
254
|
+
* @param transaction - The transaction to send.
|
|
255
|
+
* @returns The hash of the transaction.
|
|
256
|
+
*/
|
|
257
|
+
async sendTransaction(transaction) {
|
|
258
|
+
const body = {
|
|
259
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
260
|
+
chain_type: "ethereum",
|
|
261
|
+
method: "eth_sendTransaction",
|
|
262
|
+
caip2: `eip155:${__classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f").chainId}`,
|
|
263
|
+
params: {
|
|
264
|
+
transaction: {
|
|
265
|
+
...transaction,
|
|
266
|
+
from: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
try {
|
|
271
|
+
const response = await this.executePrivyRequest(body);
|
|
272
|
+
return response.data?.hash;
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
if (error instanceof Error) {
|
|
276
|
+
throw new Error(`Transaction sending failed: ${error.message}`);
|
|
277
|
+
}
|
|
278
|
+
throw new Error("Transaction sending failed");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Waits for a transaction receipt.
|
|
283
|
+
*
|
|
284
|
+
* @param txHash - The hash of the transaction to wait for.
|
|
285
|
+
* @returns The transaction receipt.
|
|
286
|
+
*/
|
|
287
|
+
async waitForTransactionReceipt(txHash) {
|
|
288
|
+
return await __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient, "f").waitForTransactionReceipt({
|
|
289
|
+
hash: txHash,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Reads data from a smart contract.
|
|
294
|
+
*
|
|
295
|
+
* @param params - Parameters for reading the contract
|
|
296
|
+
* @param params.address - The address of the contract
|
|
297
|
+
* @param params.abi - The ABI of the contract
|
|
298
|
+
* @param params.functionName - The name of the function to call
|
|
299
|
+
* @param params.args - The arguments to pass to the function
|
|
300
|
+
* @returns A Address that resolves to the contract function's return value
|
|
301
|
+
*/
|
|
302
|
+
async readContract(params) {
|
|
303
|
+
return __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient, "f").readContract(params);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Transfer the native asset of the network.
|
|
307
|
+
*
|
|
308
|
+
* @param to - The destination address.
|
|
309
|
+
* @param value - The amount to transfer in Wei.
|
|
310
|
+
* @returns The transaction hash.
|
|
311
|
+
*/
|
|
312
|
+
async nativeTransfer(to, value) {
|
|
313
|
+
const valueInWei = (0, viem_1.parseEther)(value);
|
|
314
|
+
const valueHex = `0x${valueInWei.toString(16)}`;
|
|
315
|
+
const body = {
|
|
316
|
+
address: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_address, "f"),
|
|
317
|
+
chain_type: "ethereum",
|
|
318
|
+
method: "eth_sendTransaction",
|
|
319
|
+
caip2: `eip155:${__classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f").chainId}`,
|
|
320
|
+
params: {
|
|
321
|
+
transaction: {
|
|
322
|
+
to,
|
|
323
|
+
value: valueHex,
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
try {
|
|
328
|
+
const response = await this.executePrivyRequest(body);
|
|
329
|
+
const receipt = await this.waitForTransactionReceipt(response.data.hash);
|
|
330
|
+
if (!receipt) {
|
|
331
|
+
throw new Error("Transaction failed");
|
|
332
|
+
}
|
|
333
|
+
return receipt.transactionHash;
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
if (error instanceof Error) {
|
|
337
|
+
throw new Error(`Native transfer failed: ${error.message}`);
|
|
338
|
+
}
|
|
339
|
+
throw new Error("Native transfer failed");
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Exports the wallet information.
|
|
344
|
+
*
|
|
345
|
+
* @returns The wallet data
|
|
346
|
+
*/
|
|
347
|
+
exportWallet() {
|
|
348
|
+
return {
|
|
349
|
+
walletId: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_walletId, "f"),
|
|
350
|
+
authorizationPrivateKey: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_authKey, "f"),
|
|
351
|
+
networkId: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f").networkId,
|
|
352
|
+
chainId: __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_network, "f").chainId,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Generate Privy authorization signature for API requests
|
|
357
|
+
*
|
|
358
|
+
* @param url - The URL for the request
|
|
359
|
+
* @param body - The request body
|
|
360
|
+
* @returns The generated signature
|
|
361
|
+
*/
|
|
362
|
+
generatePrivySignature(url, body) {
|
|
363
|
+
try {
|
|
364
|
+
const payload = {
|
|
365
|
+
version: 1,
|
|
366
|
+
method: "POST",
|
|
367
|
+
url,
|
|
368
|
+
body,
|
|
369
|
+
headers: {
|
|
370
|
+
"privy-app-id": __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appId, "f"),
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
const serializedPayload = (0, canonicalize_1.default)(payload);
|
|
374
|
+
if (!serializedPayload)
|
|
375
|
+
throw new Error("Failed to canonicalize payload");
|
|
376
|
+
const serializedPayloadBuffer = Buffer.from(serializedPayload);
|
|
377
|
+
const privateKeyAsString = __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_authKey, "f").replace("wallet-auth:", "");
|
|
378
|
+
const privateKeyAsPem = `-----BEGIN PRIVATE KEY-----\n${privateKeyAsString}\n-----END PRIVATE KEY-----`;
|
|
379
|
+
const privateKey = crypto_1.default.createPrivateKey({
|
|
380
|
+
key: privateKeyAsPem,
|
|
381
|
+
format: "pem",
|
|
382
|
+
});
|
|
383
|
+
const signatureBuffer = crypto_1.default.sign("sha256", serializedPayloadBuffer, privateKey);
|
|
384
|
+
return signatureBuffer.toString("base64");
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
if (error instanceof Error) {
|
|
388
|
+
throw new Error(`Error generating Privy authorization signature: ${error.message}`);
|
|
389
|
+
}
|
|
390
|
+
throw new Error("Error generating Privy authorization signature");
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Get Privy headers for API requests
|
|
395
|
+
*
|
|
396
|
+
* @param url - The URL for the request
|
|
397
|
+
* @param body - The request body
|
|
398
|
+
* @returns The headers for the request
|
|
399
|
+
*/
|
|
400
|
+
getPrivyHeaders(url, body) {
|
|
401
|
+
return {
|
|
402
|
+
"Content-Type": "application/json",
|
|
403
|
+
Authorization: `Basic ${Buffer.from(`${__classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appId, "f")}:${__classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appSecret, "f")}`).toString("base64")}`,
|
|
404
|
+
"privy-app-id": __classPrivateFieldGet(this, _PrivyEvmDelegatedEmbeddedWalletProvider_appId, "f"),
|
|
405
|
+
"privy-authorization-signature": this.generatePrivySignature(url, body),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Execute a Privy API request.
|
|
410
|
+
*
|
|
411
|
+
* @param body - The request body to send to the Privy API
|
|
412
|
+
* @returns A promise that resolves to the response data
|
|
413
|
+
* @throws Error if the request fails
|
|
414
|
+
*/
|
|
415
|
+
async executePrivyRequest(body) {
|
|
416
|
+
const url = `https://api.privy.io/v1/wallets/rpc`;
|
|
417
|
+
const headers = this.getPrivyHeaders(url, body);
|
|
418
|
+
try {
|
|
419
|
+
const response = await fetch(url, {
|
|
420
|
+
method: "POST",
|
|
421
|
+
headers,
|
|
422
|
+
body: JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value),
|
|
423
|
+
});
|
|
424
|
+
if (!response.ok) {
|
|
425
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
426
|
+
}
|
|
427
|
+
return await response.json();
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
if (error instanceof Error) {
|
|
431
|
+
throw new Error("Privy request failed: " + error.message);
|
|
432
|
+
}
|
|
433
|
+
throw new Error("Privy request failed with unknown error");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
exports.PrivyEvmDelegatedEmbeddedWalletProvider = PrivyEvmDelegatedEmbeddedWalletProvider;
|
|
438
|
+
_PrivyEvmDelegatedEmbeddedWalletProvider_walletId = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_address = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_appId = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_appSecret = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_authKey = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_network = new WeakMap(), _PrivyEvmDelegatedEmbeddedWalletProvider_publicClient = new WeakMap();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const privyEvmDelegatedEmbeddedWalletProvider_1 = require("./privyEvmDelegatedEmbeddedWalletProvider");
|
|
4
|
+
global.fetch = jest.fn().mockImplementation(async (url, init) => {
|
|
5
|
+
if (!init?.headers?.["privy-authorization-signature"]) {
|
|
6
|
+
throw new Error("Missing privy-authorization-signature header");
|
|
7
|
+
}
|
|
8
|
+
if (!init?.headers?.["privy-app-id"]) {
|
|
9
|
+
throw new Error("Missing privy-app-id header");
|
|
10
|
+
}
|
|
11
|
+
const body = JSON.parse(init.body);
|
|
12
|
+
if (url.includes("wallets/rpc")) {
|
|
13
|
+
if (body.method === "personal_sign") {
|
|
14
|
+
return Promise.resolve({
|
|
15
|
+
ok: true,
|
|
16
|
+
json: () => Promise.resolve({ data: { signature: "0x1234" } }),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (body.method === "eth_signTypedData_v4") {
|
|
20
|
+
return Promise.resolve({
|
|
21
|
+
ok: true,
|
|
22
|
+
json: () => Promise.resolve({ signature: "0x1234" }),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (body.method === "eth_signTransaction") {
|
|
26
|
+
return Promise.resolve({
|
|
27
|
+
ok: true,
|
|
28
|
+
json: () => Promise.resolve({ data: { signed_transaction: "0x1234" } }),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (body.method === "eth_sendTransaction") {
|
|
32
|
+
return Promise.resolve({
|
|
33
|
+
ok: true,
|
|
34
|
+
json: () => Promise.resolve({ data: { hash: "0xef01" } }),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return Promise.resolve({
|
|
39
|
+
ok: true,
|
|
40
|
+
json: () => Promise.resolve({}),
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
jest.mock("../analytics", () => ({
|
|
44
|
+
sendAnalyticsEvent: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
45
|
+
}));
|
|
46
|
+
const MOCK_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
|
|
47
|
+
const MOCK_WALLET_ID = "test-wallet-id";
|
|
48
|
+
const MOCK_TRANSACTION_HASH = "0xef01";
|
|
49
|
+
const MOCK_SIGNATURE = "0x1234";
|
|
50
|
+
jest.mock("../network", () => {
|
|
51
|
+
const chain = {
|
|
52
|
+
id: 84532,
|
|
53
|
+
name: "Base Sepolia",
|
|
54
|
+
rpcUrls: {
|
|
55
|
+
default: { http: ["https://sepolia.base.org"] },
|
|
56
|
+
},
|
|
57
|
+
nativeCurrency: {
|
|
58
|
+
name: "Ether",
|
|
59
|
+
symbol: "ETH",
|
|
60
|
+
decimals: 18,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
65
|
+
protocolFamily: "evm",
|
|
66
|
+
chainId: "84532",
|
|
67
|
+
networkId: "base-sepolia",
|
|
68
|
+
}),
|
|
69
|
+
getChain: jest.fn().mockReturnValue(chain),
|
|
70
|
+
NETWORK_ID_TO_CHAIN_ID: {
|
|
71
|
+
"base-sepolia": "84532",
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
jest.mock("viem", () => {
|
|
76
|
+
const originalModule = jest.requireActual("viem");
|
|
77
|
+
return {
|
|
78
|
+
...originalModule,
|
|
79
|
+
createPublicClient: jest.fn().mockReturnValue({
|
|
80
|
+
getBalance: jest.fn().mockResolvedValue(BigInt(1000000000000000000)),
|
|
81
|
+
waitForTransactionReceipt: jest.fn().mockResolvedValue({
|
|
82
|
+
transactionHash: "0xef01",
|
|
83
|
+
status: "success",
|
|
84
|
+
}),
|
|
85
|
+
readContract: jest.fn().mockResolvedValue("mock_result"),
|
|
86
|
+
}),
|
|
87
|
+
parseEther: jest.fn().mockReturnValue(BigInt(1000000000000000000)),
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
jest.mock("./privyShared", () => ({
|
|
91
|
+
createPrivyClient: jest.fn().mockReturnValue({
|
|
92
|
+
getUser: jest.fn().mockResolvedValue({
|
|
93
|
+
linkedAccounts: [
|
|
94
|
+
{
|
|
95
|
+
type: "wallet",
|
|
96
|
+
walletClientType: "privy",
|
|
97
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
101
|
+
}),
|
|
102
|
+
}));
|
|
103
|
+
jest.mock("canonicalize", () => {
|
|
104
|
+
const mockFn = jest.fn().mockImplementation((obj) => {
|
|
105
|
+
const replacer = (key, value) => {
|
|
106
|
+
if (typeof value === "bigint") {
|
|
107
|
+
return value.toString();
|
|
108
|
+
}
|
|
109
|
+
return value;
|
|
110
|
+
};
|
|
111
|
+
return JSON.stringify(obj, replacer);
|
|
112
|
+
});
|
|
113
|
+
return mockFn;
|
|
114
|
+
});
|
|
115
|
+
jest.mock("crypto", () => ({
|
|
116
|
+
createPrivateKey: jest.fn().mockImplementation(() => ({})),
|
|
117
|
+
sign: jest.fn().mockImplementation(() => Buffer.from("mock-signature")),
|
|
118
|
+
}));
|
|
119
|
+
describe("PrivyEvmDelegatedEmbeddedWalletProvider", () => {
|
|
120
|
+
const MOCK_CONFIG = {
|
|
121
|
+
appId: "test-app-id",
|
|
122
|
+
appSecret: "test-app-secret",
|
|
123
|
+
authorizationPrivateKey: "wallet-auth:test-auth-key",
|
|
124
|
+
walletId: MOCK_WALLET_ID,
|
|
125
|
+
networkId: "base-sepolia",
|
|
126
|
+
};
|
|
127
|
+
beforeEach(() => {
|
|
128
|
+
jest.clearAllMocks();
|
|
129
|
+
});
|
|
130
|
+
describe("configureWithWallet", () => {
|
|
131
|
+
it("should configure with required configuration", async () => {
|
|
132
|
+
const provider = await privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(MOCK_CONFIG);
|
|
133
|
+
expect(provider).toBeInstanceOf(privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider);
|
|
134
|
+
expect(provider.getNetwork()).toEqual({
|
|
135
|
+
protocolFamily: "evm",
|
|
136
|
+
chainId: "84532",
|
|
137
|
+
networkId: "base-sepolia",
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
it("should throw error if walletId is missing", async () => {
|
|
141
|
+
const { walletId: _walletId, ...configWithoutWalletId } = MOCK_CONFIG;
|
|
142
|
+
await expect(privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(configWithoutWalletId)).rejects.toThrow("walletId is required");
|
|
143
|
+
});
|
|
144
|
+
it("should throw error if appId or appSecret is missing", async () => {
|
|
145
|
+
const { appId: _appId, ...configWithoutAppId } = MOCK_CONFIG;
|
|
146
|
+
await expect(privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(configWithoutAppId)).rejects.toThrow("appId and appSecret are required");
|
|
147
|
+
});
|
|
148
|
+
it("should throw error if authorizationPrivateKey is missing", async () => {
|
|
149
|
+
const { authorizationPrivateKey: _authKey, ...configWithoutAuthKey } = MOCK_CONFIG;
|
|
150
|
+
await expect(privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(configWithoutAuthKey)).rejects.toThrow("authorizationPrivateKey is required");
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe("wallet methods", () => {
|
|
154
|
+
let provider;
|
|
155
|
+
beforeEach(async () => {
|
|
156
|
+
provider = await privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(MOCK_CONFIG);
|
|
157
|
+
});
|
|
158
|
+
it("should get the wallet address", () => {
|
|
159
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
160
|
+
});
|
|
161
|
+
it("should get the network information", () => {
|
|
162
|
+
expect(provider.getNetwork()).toEqual({
|
|
163
|
+
protocolFamily: "evm",
|
|
164
|
+
chainId: "84532",
|
|
165
|
+
networkId: "base-sepolia",
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
it("should get the provider name", () => {
|
|
169
|
+
expect(provider.getName()).toBe("privy_evm_embedded_wallet_provider");
|
|
170
|
+
});
|
|
171
|
+
it("should get the wallet balance", async () => {
|
|
172
|
+
const balance = await provider.getBalance();
|
|
173
|
+
expect(balance).toBe(BigInt(1000000000000000000));
|
|
174
|
+
});
|
|
175
|
+
it("should sign a message", async () => {
|
|
176
|
+
const result = await provider.signMessage("Hello, world!");
|
|
177
|
+
expect(result).toBe(MOCK_SIGNATURE);
|
|
178
|
+
});
|
|
179
|
+
it("should sign typed data", async () => {
|
|
180
|
+
const typedData = {
|
|
181
|
+
domain: { name: "Test" },
|
|
182
|
+
types: { Test: [{ name: "test", type: "string" }] },
|
|
183
|
+
primaryType: "Test",
|
|
184
|
+
message: { test: "test" },
|
|
185
|
+
};
|
|
186
|
+
const result = await provider.signTypedData(typedData);
|
|
187
|
+
expect(result).toBe(MOCK_SIGNATURE);
|
|
188
|
+
});
|
|
189
|
+
it("should sign a transaction", async () => {
|
|
190
|
+
const transaction = {
|
|
191
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
192
|
+
value: BigInt(1000000000000000000),
|
|
193
|
+
};
|
|
194
|
+
const result = await provider.signTransaction(transaction);
|
|
195
|
+
expect(result).toBe(MOCK_SIGNATURE);
|
|
196
|
+
});
|
|
197
|
+
it("should send a transaction", async () => {
|
|
198
|
+
const transaction = {
|
|
199
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
200
|
+
value: BigInt(1000000000000000000),
|
|
201
|
+
};
|
|
202
|
+
const result = await provider.sendTransaction(transaction);
|
|
203
|
+
expect(result).toBe(MOCK_TRANSACTION_HASH);
|
|
204
|
+
});
|
|
205
|
+
it("should wait for transaction receipt", async () => {
|
|
206
|
+
const receipt = await provider.waitForTransactionReceipt(MOCK_TRANSACTION_HASH);
|
|
207
|
+
expect(receipt).toEqual({
|
|
208
|
+
transactionHash: MOCK_TRANSACTION_HASH,
|
|
209
|
+
status: "success",
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
it("should transfer native tokens", async () => {
|
|
213
|
+
const result = await provider.nativeTransfer("0x1234567890123456789012345678901234567890", "1.0");
|
|
214
|
+
expect(result).toBe(MOCK_TRANSACTION_HASH);
|
|
215
|
+
});
|
|
216
|
+
it("should export wallet data", () => {
|
|
217
|
+
const exportData = provider.exportWallet();
|
|
218
|
+
expect(exportData).toEqual({
|
|
219
|
+
walletId: MOCK_WALLET_ID,
|
|
220
|
+
authorizationPrivateKey: MOCK_CONFIG.authorizationPrivateKey,
|
|
221
|
+
networkId: "base-sepolia",
|
|
222
|
+
chainId: "84532",
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
it("should read contract data", async () => {
|
|
226
|
+
const abi = [
|
|
227
|
+
{
|
|
228
|
+
name: "balanceOf",
|
|
229
|
+
type: "function",
|
|
230
|
+
inputs: [{ name: "account", type: "address" }],
|
|
231
|
+
outputs: [{ name: "balance", type: "uint256" }],
|
|
232
|
+
stateMutability: "view",
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
const result = await provider.readContract({
|
|
236
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
237
|
+
abi,
|
|
238
|
+
functionName: "balanceOf",
|
|
239
|
+
args: [MOCK_ADDRESS],
|
|
240
|
+
});
|
|
241
|
+
expect(result).toBe("mock_result");
|
|
242
|
+
});
|
|
243
|
+
describe("request signing", () => {
|
|
244
|
+
it("should include required headers in requests", async () => {
|
|
245
|
+
const transaction = {
|
|
246
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
247
|
+
value: BigInt(1000000000000000000),
|
|
248
|
+
};
|
|
249
|
+
await provider.sendTransaction(transaction);
|
|
250
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
251
|
+
const lastCall = global.fetch.mock.calls[global.fetch.mock.calls.length - 1];
|
|
252
|
+
const [_url, init] = lastCall;
|
|
253
|
+
expect(init.headers).toBeDefined();
|
|
254
|
+
expect(init.headers["privy-authorization-signature"]).toBeDefined();
|
|
255
|
+
expect(init.headers["privy-app-id"]).toBe("test-app-id");
|
|
256
|
+
expect(init.headers["Authorization"]).toBeDefined();
|
|
257
|
+
});
|
|
258
|
+
it("should handle signature generation errors", async () => {
|
|
259
|
+
const canonicalize = jest.requireMock("canonicalize");
|
|
260
|
+
canonicalize.mockImplementationOnce(() => null); // Force canonicalization failure
|
|
261
|
+
const transaction = {
|
|
262
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
263
|
+
value: BigInt(1000000000000000000),
|
|
264
|
+
};
|
|
265
|
+
await expect(provider.sendTransaction(transaction)).rejects.toThrow("Error generating Privy authorization signature");
|
|
266
|
+
});
|
|
267
|
+
it("should handle HTTP errors", async () => {
|
|
268
|
+
global.fetch.mockImplementationOnce(() => Promise.resolve({
|
|
269
|
+
ok: false,
|
|
270
|
+
status: 400,
|
|
271
|
+
}));
|
|
272
|
+
const transaction = {
|
|
273
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
274
|
+
value: BigInt(1000000000000000000),
|
|
275
|
+
};
|
|
276
|
+
await expect(provider.sendTransaction(transaction)).rejects.toThrow("Privy request failed: HTTP error! status: 400");
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
@@ -17,6 +17,8 @@ export interface PrivyWalletConfig {
|
|
|
17
17
|
authorizationKeyId?: string;
|
|
18
18
|
/** The chain type to create the wallet on */
|
|
19
19
|
chainType?: "ethereum" | "solana";
|
|
20
|
+
/** The type of wallet to use */
|
|
21
|
+
walletType?: "server" | "embedded";
|
|
20
22
|
}
|
|
21
23
|
export type PrivyWalletExport = {
|
|
22
24
|
walletId: string;
|
|
@@ -30,6 +32,13 @@ type CreatePrivyWalletReturnType = {
|
|
|
30
32
|
};
|
|
31
33
|
privy: PrivyClient;
|
|
32
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Create a Privy client
|
|
37
|
+
*
|
|
38
|
+
* @param config - The configuration options for the Privy client
|
|
39
|
+
* @returns The created Privy client
|
|
40
|
+
*/
|
|
41
|
+
export declare const createPrivyClient: (config: PrivyWalletConfig) => PrivyClient;
|
|
33
42
|
/**
|
|
34
43
|
* Create a Privy wallet
|
|
35
44
|
*
|
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPrivyClient = void 0;
|
|
3
4
|
exports.createPrivyWallet = createPrivyWallet;
|
|
4
5
|
const server_auth_1 = require("@privy-io/server-auth");
|
|
5
6
|
/**
|
|
6
|
-
* Create a Privy
|
|
7
|
+
* Create a Privy client
|
|
7
8
|
*
|
|
8
|
-
* @param config - The configuration options for the Privy
|
|
9
|
-
* @returns The created Privy
|
|
9
|
+
* @param config - The configuration options for the Privy client
|
|
10
|
+
* @returns The created Privy client
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const createPrivyClient = (config) => {
|
|
13
|
+
return new server_auth_1.PrivyClient(config.appId, config.appSecret, {
|
|
13
14
|
walletApi: config.authorizationPrivateKey
|
|
14
15
|
? {
|
|
15
16
|
authorizationPrivateKey: config.authorizationPrivateKey,
|
|
16
17
|
}
|
|
17
18
|
: undefined,
|
|
18
19
|
});
|
|
20
|
+
};
|
|
21
|
+
exports.createPrivyClient = createPrivyClient;
|
|
22
|
+
/**
|
|
23
|
+
* Create a Privy wallet
|
|
24
|
+
*
|
|
25
|
+
* @param config - The configuration options for the Privy wallet
|
|
26
|
+
* @returns The created Privy wallet
|
|
27
|
+
*/
|
|
28
|
+
async function createPrivyWallet(config) {
|
|
29
|
+
const privy = (0, exports.createPrivyClient)(config);
|
|
19
30
|
if (config.walletId) {
|
|
20
31
|
const wallet = await privy.walletApi.getWallet({ id: config.walletId });
|
|
21
32
|
if (!wallet) {
|
|
@@ -1,35 +1,48 @@
|
|
|
1
1
|
import { PrivyEvmWalletProvider, PrivyEvmWalletConfig } from "./privyEvmWalletProvider";
|
|
2
2
|
import { PrivySvmWalletProvider, PrivySvmWalletConfig } from "./privySvmWalletProvider";
|
|
3
|
-
|
|
3
|
+
import { PrivyEvmDelegatedEmbeddedWalletProvider, PrivyEvmDelegatedEmbeddedWalletConfig } from "./privyEvmDelegatedEmbeddedWalletProvider";
|
|
4
|
+
export type PrivyWalletConfig = PrivyEvmWalletConfig | PrivySvmWalletConfig | PrivyEvmDelegatedEmbeddedWalletConfig;
|
|
5
|
+
export type PrivyWalletProviderVariant<T> = T extends {
|
|
6
|
+
walletType: "embedded";
|
|
7
|
+
} ? PrivyEvmDelegatedEmbeddedWalletProvider : T extends {
|
|
8
|
+
chainType: "solana";
|
|
9
|
+
} ? PrivySvmWalletProvider : PrivyEvmWalletProvider;
|
|
4
10
|
/**
|
|
5
11
|
* Factory class for creating chain-specific Privy wallet providers
|
|
6
12
|
*/
|
|
7
13
|
export declare class PrivyWalletProvider {
|
|
8
14
|
/**
|
|
9
|
-
* Creates and configures a new wallet provider instance based on the chain type.
|
|
15
|
+
* Creates and configures a new wallet provider instance based on the chain type and wallet type.
|
|
10
16
|
*
|
|
11
17
|
* @param config - The configuration options for the Privy wallet
|
|
12
|
-
* @returns A configured WalletProvider instance for the specified chain
|
|
18
|
+
* @returns A configured WalletProvider instance for the specified chain and wallet type
|
|
13
19
|
*
|
|
14
20
|
* @example
|
|
15
21
|
* ```typescript
|
|
16
|
-
* // For EVM (default)
|
|
22
|
+
* // For EVM server wallets (default)
|
|
17
23
|
* const evmWallet = await PrivyWalletProvider.configureWithWallet({
|
|
18
24
|
* appId: "your-app-id",
|
|
19
25
|
* appSecret: "your-app-secret"
|
|
20
26
|
* });
|
|
21
27
|
*
|
|
22
|
-
* // For Solana
|
|
28
|
+
* // For Solana server wallets
|
|
23
29
|
* const solanaWallet = await PrivyWalletProvider.configureWithWallet({
|
|
24
30
|
* appId: "your-app-id",
|
|
25
31
|
* appSecret: "your-app-secret",
|
|
26
32
|
* chainType: "solana"
|
|
27
33
|
* });
|
|
34
|
+
*
|
|
35
|
+
* // For Ethereum embedded wallets
|
|
36
|
+
* const embeddedWallet = await PrivyWalletProvider.configureWithWallet({
|
|
37
|
+
* appId: "your-app-id",
|
|
38
|
+
* appSecret: "your-app-secret",
|
|
39
|
+
* walletId: "delegated-wallet-id",
|
|
40
|
+
* walletType: "embedded"
|
|
41
|
+
* });
|
|
28
42
|
* ```
|
|
29
43
|
*/
|
|
30
44
|
static configureWithWallet<T extends PrivyWalletConfig>(config: T & {
|
|
31
45
|
chainType?: "ethereum" | "solana";
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} ? PrivySvmWalletProvider : PrivyEvmWalletProvider>;
|
|
46
|
+
walletType?: "server" | "embedded";
|
|
47
|
+
}): Promise<PrivyWalletProviderVariant<T>>;
|
|
35
48
|
}
|
|
@@ -3,37 +3,69 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PrivyWalletProvider = void 0;
|
|
4
4
|
const privyEvmWalletProvider_1 = require("./privyEvmWalletProvider");
|
|
5
5
|
const privySvmWalletProvider_1 = require("./privySvmWalletProvider");
|
|
6
|
+
const privyEvmDelegatedEmbeddedWalletProvider_1 = require("./privyEvmDelegatedEmbeddedWalletProvider");
|
|
6
7
|
/**
|
|
7
8
|
* Factory class for creating chain-specific Privy wallet providers
|
|
8
9
|
*/
|
|
9
10
|
class PrivyWalletProvider {
|
|
10
11
|
/**
|
|
11
|
-
* Creates and configures a new wallet provider instance based on the chain type.
|
|
12
|
+
* Creates and configures a new wallet provider instance based on the chain type and wallet type.
|
|
12
13
|
*
|
|
13
14
|
* @param config - The configuration options for the Privy wallet
|
|
14
|
-
* @returns A configured WalletProvider instance for the specified chain
|
|
15
|
+
* @returns A configured WalletProvider instance for the specified chain and wallet type
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```typescript
|
|
18
|
-
* // For EVM (default)
|
|
19
|
+
* // For EVM server wallets (default)
|
|
19
20
|
* const evmWallet = await PrivyWalletProvider.configureWithWallet({
|
|
20
21
|
* appId: "your-app-id",
|
|
21
22
|
* appSecret: "your-app-secret"
|
|
22
23
|
* });
|
|
23
24
|
*
|
|
24
|
-
* // For Solana
|
|
25
|
+
* // For Solana server wallets
|
|
25
26
|
* const solanaWallet = await PrivyWalletProvider.configureWithWallet({
|
|
26
27
|
* appId: "your-app-id",
|
|
27
28
|
* appSecret: "your-app-secret",
|
|
28
29
|
* chainType: "solana"
|
|
29
30
|
* });
|
|
31
|
+
*
|
|
32
|
+
* // For Ethereum embedded wallets
|
|
33
|
+
* const embeddedWallet = await PrivyWalletProvider.configureWithWallet({
|
|
34
|
+
* appId: "your-app-id",
|
|
35
|
+
* appSecret: "your-app-secret",
|
|
36
|
+
* walletId: "delegated-wallet-id",
|
|
37
|
+
* walletType: "embedded"
|
|
38
|
+
* });
|
|
30
39
|
* ```
|
|
31
40
|
*/
|
|
32
41
|
static async configureWithWallet(config) {
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
const chainType = config.chainType || "ethereum";
|
|
43
|
+
const walletType = config.walletType || "server";
|
|
44
|
+
switch (chainType) {
|
|
45
|
+
case "ethereum": {
|
|
46
|
+
switch (walletType) {
|
|
47
|
+
case "server":
|
|
48
|
+
return (await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet(config));
|
|
49
|
+
case "embedded":
|
|
50
|
+
return (await privyEvmDelegatedEmbeddedWalletProvider_1.PrivyEvmDelegatedEmbeddedWalletProvider.configureWithWallet(config));
|
|
51
|
+
default:
|
|
52
|
+
throw new Error("Invalid wallet type");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
case "solana": {
|
|
56
|
+
switch (walletType) {
|
|
57
|
+
case "server":
|
|
58
|
+
return (await privySvmWalletProvider_1.PrivySvmWalletProvider.configureWithWallet(config));
|
|
59
|
+
case "embedded":
|
|
60
|
+
throw new Error("Embedded wallets are not supported for Solana");
|
|
61
|
+
default:
|
|
62
|
+
throw new Error("Invalid wallet type");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
default: {
|
|
66
|
+
throw new Error("Invalid chain type");
|
|
67
|
+
}
|
|
35
68
|
}
|
|
36
|
-
return (await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet(config));
|
|
37
69
|
}
|
|
38
70
|
}
|
|
39
71
|
exports.PrivyWalletProvider = PrivyWalletProvider;
|
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.0.0-nightly-
|
|
5
|
+
"version": "0.0.0-nightly-20250328210410",
|
|
6
6
|
"author": "Coinbase Inc.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"main": "dist/index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@solana/spl-token": "^0.4.12",
|
|
31
31
|
"@solana/web3.js": "^1.98.0",
|
|
32
32
|
"bs58": "^4.0.1",
|
|
33
|
+
"canonicalize": "^2.1.0",
|
|
33
34
|
"decimal.js": "^10.5.0",
|
|
34
35
|
"ethers": "^6.13.5",
|
|
35
36
|
"md5": "^2.3.0",
|