@coinbase/agentkit 0.4.0 → 0.5.0
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 +73 -7
- package/dist/action-providers/across/acrossActionProvider.d.ts +50 -0
- package/dist/action-providers/across/acrossActionProvider.js +333 -0
- package/dist/action-providers/across/acrossActionProvider.test.d.ts +1 -0
- package/dist/action-providers/across/acrossActionProvider.test.js +391 -0
- package/dist/action-providers/across/constants.d.ts +1 -0
- package/dist/action-providers/across/constants.js +2 -0
- package/dist/action-providers/across/index.d.ts +1 -0
- package/dist/action-providers/across/index.js +17 -0
- package/dist/action-providers/across/schemas.d.ts +36 -0
- package/dist/action-providers/across/schemas.js +46 -0
- package/dist/action-providers/across/utils.d.ts +7 -0
- package/dist/action-providers/across/utils.js +25 -0
- package/dist/action-providers/erc20/constants.d.ts +2 -0
- package/dist/action-providers/erc20/constants.js +12 -1
- package/dist/action-providers/erc20/erc20ActionProvider.js +18 -0
- package/dist/action-providers/erc20/erc20ActionProvider.test.js +4 -0
- package/dist/action-providers/index.d.ts +2 -0
- package/dist/action-providers/index.js +2 -0
- package/dist/action-providers/messari/constants.d.ts +17 -0
- package/dist/action-providers/messari/constants.js +20 -0
- package/dist/action-providers/messari/index.d.ts +5 -0
- package/dist/action-providers/messari/index.js +21 -0
- package/dist/action-providers/messari/messariActionProvider.d.ts +42 -0
- package/dist/action-providers/messari/messariActionProvider.js +128 -0
- package/dist/action-providers/messari/messariActionProvider.test.d.ts +1 -0
- package/dist/action-providers/messari/messariActionProvider.test.js +152 -0
- package/dist/action-providers/messari/schemas.d.ts +11 -0
- package/dist/action-providers/messari/schemas.js +16 -0
- package/dist/action-providers/messari/types.d.ts +40 -0
- package/dist/action-providers/messari/types.js +2 -0
- package/dist/action-providers/messari/utils.d.ts +22 -0
- package/dist/action-providers/messari/utils.js +65 -0
- package/dist/wallet-providers/cdpWalletProvider.d.ts +11 -2
- package/dist/wallet-providers/cdpWalletProvider.js +24 -0
- package/dist/wallet-providers/cdpWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/cdpWalletProvider.test.js +701 -0
- package/dist/wallet-providers/evmWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/evmWalletProvider.test.js +56 -0
- 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/privyEvmWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/privyEvmWalletProvider.test.js +331 -0
- package/dist/wallet-providers/privyShared.d.ts +9 -0
- package/dist/wallet-providers/privyShared.js +16 -5
- package/dist/wallet-providers/privySvmWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/privySvmWalletProvider.test.js +310 -0
- package/dist/wallet-providers/privyWalletProvider.d.ts +21 -8
- package/dist/wallet-providers/privyWalletProvider.js +39 -7
- package/dist/wallet-providers/privyWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/privyWalletProvider.test.js +124 -0
- package/dist/wallet-providers/smartWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/smartWalletProvider.test.js +388 -0
- package/dist/wallet-providers/solanaKeypairWalletProvider.test.js +210 -16
- package/dist/wallet-providers/svmWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/svmWalletProvider.test.js +55 -0
- package/dist/wallet-providers/viemWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/viemWalletProvider.test.js +338 -0
- package/dist/wallet-providers/walletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/walletProvider.test.js +103 -0
- package/package.json +24 -20
|
@@ -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
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const privyEvmWalletProvider_1 = require("./privyEvmWalletProvider");
|
|
4
|
+
global.fetch = jest.fn(() => Promise.resolve({
|
|
5
|
+
ok: true,
|
|
6
|
+
json: () => Promise.resolve({}),
|
|
7
|
+
}));
|
|
8
|
+
jest.mock("../analytics", () => ({
|
|
9
|
+
sendAnalyticsEvent: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
10
|
+
}));
|
|
11
|
+
const MOCK_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
|
|
12
|
+
const MOCK_WALLET_ID = "test-wallet-id";
|
|
13
|
+
const MOCK_TRANSACTION_HASH = "0xef01";
|
|
14
|
+
const MOCK_SIGNATURE_HASH_1 = "0x1234";
|
|
15
|
+
const MOCK_SIGNATURE_HASH_2 = "0x5678";
|
|
16
|
+
const MOCK_SIGNATURE_HASH_3 = "0xabcd";
|
|
17
|
+
jest.mock("@privy-io/server-auth", () => ({
|
|
18
|
+
PrivyClient: jest.fn().mockImplementation(() => ({
|
|
19
|
+
appId: "mock-app-id",
|
|
20
|
+
walletApi: {
|
|
21
|
+
create: jest.fn().mockResolvedValue({
|
|
22
|
+
id: "test-wallet-id",
|
|
23
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
24
|
+
}),
|
|
25
|
+
getWallet: jest.fn().mockResolvedValue({
|
|
26
|
+
id: "test-wallet-id",
|
|
27
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
})),
|
|
31
|
+
}));
|
|
32
|
+
jest.mock("@privy-io/server-auth/viem", () => ({
|
|
33
|
+
getWalletClient: jest.fn().mockReturnValue({
|
|
34
|
+
account: {
|
|
35
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
36
|
+
},
|
|
37
|
+
chain: {
|
|
38
|
+
id: 1,
|
|
39
|
+
name: "Ethereum",
|
|
40
|
+
rpcUrls: {
|
|
41
|
+
default: { http: ["https://eth.llamarpc.com"] },
|
|
42
|
+
},
|
|
43
|
+
nativeCurrency: {
|
|
44
|
+
name: "Ether",
|
|
45
|
+
symbol: "ETH",
|
|
46
|
+
decimals: 18,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
signMessage: jest.fn().mockResolvedValue("0x1234"),
|
|
50
|
+
signTypedData: jest.fn().mockResolvedValue("0x5678"),
|
|
51
|
+
signTransaction: jest.fn().mockResolvedValue("0xabcd"),
|
|
52
|
+
sendTransaction: jest.fn().mockResolvedValue("0xef01"),
|
|
53
|
+
}),
|
|
54
|
+
getPublicClient: jest.fn().mockReturnValue({
|
|
55
|
+
getChainId: jest.fn().mockResolvedValue(1),
|
|
56
|
+
getBalance: jest.fn().mockResolvedValue(BigInt(1000000000000000000)),
|
|
57
|
+
waitForTransactionReceipt: jest.fn().mockResolvedValue({ transactionHash: "0xef01" }),
|
|
58
|
+
readContract: jest.fn().mockResolvedValue("mock_result"),
|
|
59
|
+
estimateFeesPerGas: jest.fn().mockResolvedValue({
|
|
60
|
+
maxFeePerGas: BigInt(100000000),
|
|
61
|
+
maxPriorityFeePerGas: BigInt(10000000),
|
|
62
|
+
}),
|
|
63
|
+
estimateGas: jest.fn().mockResolvedValue(BigInt(21000)),
|
|
64
|
+
}),
|
|
65
|
+
createViemAccount: jest.fn().mockResolvedValue({
|
|
66
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
67
|
+
type: "local",
|
|
68
|
+
signMessage: jest.fn().mockResolvedValue("0x1234"),
|
|
69
|
+
signTypedData: jest.fn().mockResolvedValue("0x5678"),
|
|
70
|
+
signTransaction: jest.fn().mockResolvedValue("0xabcd"),
|
|
71
|
+
}),
|
|
72
|
+
}));
|
|
73
|
+
jest.mock("../network", () => {
|
|
74
|
+
const chain = {
|
|
75
|
+
id: 1,
|
|
76
|
+
name: "Ethereum",
|
|
77
|
+
rpcUrls: {
|
|
78
|
+
default: { http: ["https://eth.llamarpc.com"] },
|
|
79
|
+
},
|
|
80
|
+
nativeCurrency: {
|
|
81
|
+
name: "Ether",
|
|
82
|
+
symbol: "ETH",
|
|
83
|
+
decimals: 18,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
88
|
+
protocolFamily: "evm",
|
|
89
|
+
chainId: "1",
|
|
90
|
+
networkId: "ethereum-mainnet",
|
|
91
|
+
}),
|
|
92
|
+
getChain: jest.fn().mockReturnValue(chain),
|
|
93
|
+
CHAIN_ID_TO_NETWORK_ID: {
|
|
94
|
+
"1": "ethereum-mainnet",
|
|
95
|
+
"5": "ethereum-goerli",
|
|
96
|
+
"11155111": "ethereum-sepolia",
|
|
97
|
+
},
|
|
98
|
+
NETWORK_ID_TO_CHAIN_ID: {
|
|
99
|
+
"ethereum-mainnet": "1",
|
|
100
|
+
"ethereum-goerli": "5",
|
|
101
|
+
"ethereum-sepolia": "11155111",
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
jest.mock("viem", () => {
|
|
106
|
+
const originalModule = jest.requireActual("viem");
|
|
107
|
+
return {
|
|
108
|
+
...originalModule,
|
|
109
|
+
createPublicClient: jest.fn().mockReturnValue({
|
|
110
|
+
getChainId: jest.fn().mockResolvedValue(1),
|
|
111
|
+
getBalance: jest.fn().mockResolvedValue(BigInt(1000000000000000000)),
|
|
112
|
+
waitForTransactionReceipt: jest.fn().mockResolvedValue({ transactionHash: "0xef01" }),
|
|
113
|
+
readContract: jest.fn().mockResolvedValue("mock_result"),
|
|
114
|
+
estimateFeesPerGas: jest.fn().mockResolvedValue({
|
|
115
|
+
maxFeePerGas: BigInt(100000000),
|
|
116
|
+
maxPriorityFeePerGas: BigInt(10000000),
|
|
117
|
+
}),
|
|
118
|
+
estimateGas: jest.fn().mockResolvedValue(BigInt(21000)),
|
|
119
|
+
}),
|
|
120
|
+
createWalletClient: jest.fn().mockReturnValue({
|
|
121
|
+
account: {
|
|
122
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
123
|
+
},
|
|
124
|
+
chain: {
|
|
125
|
+
id: 1,
|
|
126
|
+
name: "Ethereum",
|
|
127
|
+
rpcUrls: {
|
|
128
|
+
default: { http: ["https://eth.llamarpc.com"] },
|
|
129
|
+
},
|
|
130
|
+
nativeCurrency: {
|
|
131
|
+
name: "Ether",
|
|
132
|
+
symbol: "ETH",
|
|
133
|
+
decimals: 18,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
signMessage: jest.fn().mockResolvedValue("0x1234"),
|
|
137
|
+
signTypedData: jest.fn().mockResolvedValue("0x5678"),
|
|
138
|
+
signTransaction: jest.fn().mockResolvedValue("0xabcd"),
|
|
139
|
+
sendTransaction: jest.fn().mockResolvedValue("0xef01"),
|
|
140
|
+
}),
|
|
141
|
+
parseEther: jest.fn().mockReturnValue(BigInt(1000000000000000000)),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
jest.mock("./privyShared", () => ({
|
|
145
|
+
createPrivyWallet: jest.fn().mockResolvedValue({
|
|
146
|
+
wallet: {
|
|
147
|
+
id: "test-wallet-id",
|
|
148
|
+
address: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
|
149
|
+
},
|
|
150
|
+
privy: {
|
|
151
|
+
appId: "mock-app-id",
|
|
152
|
+
walletApi: {
|
|
153
|
+
create: jest.fn(),
|
|
154
|
+
getWallet: jest.fn(),
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
}),
|
|
158
|
+
}));
|
|
159
|
+
describe("PrivyEvmWalletProvider", () => {
|
|
160
|
+
const MOCK_CONFIG = {
|
|
161
|
+
appId: "mock-app-id",
|
|
162
|
+
apiKey: "mock-api-key",
|
|
163
|
+
appSecret: "mock-app-secret",
|
|
164
|
+
networkId: "ethereum-mainnet",
|
|
165
|
+
};
|
|
166
|
+
beforeEach(() => {
|
|
167
|
+
jest.clearAllMocks();
|
|
168
|
+
});
|
|
169
|
+
describe("configureWithWallet", () => {
|
|
170
|
+
it("should configure a wallet with required configuration", async () => {
|
|
171
|
+
const provider = await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet(MOCK_CONFIG);
|
|
172
|
+
expect(provider).toBeInstanceOf(privyEvmWalletProvider_1.PrivyEvmWalletProvider);
|
|
173
|
+
expect(provider.getNetwork()).toEqual({
|
|
174
|
+
protocolFamily: "evm",
|
|
175
|
+
chainId: "1",
|
|
176
|
+
networkId: "ethereum-mainnet",
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it("should configure a wallet with chain ID", async () => {
|
|
180
|
+
const provider = await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet({
|
|
181
|
+
...MOCK_CONFIG,
|
|
182
|
+
chainId: "5",
|
|
183
|
+
});
|
|
184
|
+
expect(provider).toBeInstanceOf(privyEvmWalletProvider_1.PrivyEvmWalletProvider);
|
|
185
|
+
expect(provider.getNetwork()).toEqual({
|
|
186
|
+
protocolFamily: "evm",
|
|
187
|
+
chainId: "1",
|
|
188
|
+
networkId: "ethereum-mainnet",
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
it("should configure a wallet with existing wallet ID", async () => {
|
|
192
|
+
const provider = await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet({
|
|
193
|
+
...MOCK_CONFIG,
|
|
194
|
+
walletId: "existing-wallet-id",
|
|
195
|
+
});
|
|
196
|
+
expect(provider).toBeInstanceOf(privyEvmWalletProvider_1.PrivyEvmWalletProvider);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
describe("wallet methods", () => {
|
|
200
|
+
let provider;
|
|
201
|
+
beforeEach(async () => {
|
|
202
|
+
provider = await privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet(MOCK_CONFIG);
|
|
203
|
+
});
|
|
204
|
+
it("should get the wallet address", () => {
|
|
205
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
206
|
+
});
|
|
207
|
+
it("should get the network information", () => {
|
|
208
|
+
expect(provider.getNetwork()).toEqual({
|
|
209
|
+
protocolFamily: "evm",
|
|
210
|
+
chainId: "1",
|
|
211
|
+
networkId: "ethereum-mainnet",
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
it("should get the provider name", () => {
|
|
215
|
+
expect(provider.getName()).toBe("privy_evm_wallet_provider");
|
|
216
|
+
});
|
|
217
|
+
it("should sign a message", async () => {
|
|
218
|
+
const result = await provider.signMessage("Hello, world!");
|
|
219
|
+
expect(result).toBe(MOCK_SIGNATURE_HASH_1);
|
|
220
|
+
});
|
|
221
|
+
it("should sign typed data", async () => {
|
|
222
|
+
const typedData = {
|
|
223
|
+
domain: { name: "Test" },
|
|
224
|
+
types: { Test: [{ name: "test", type: "string" }] },
|
|
225
|
+
primaryType: "Test",
|
|
226
|
+
message: { test: "test" },
|
|
227
|
+
};
|
|
228
|
+
const result = await provider.signTypedData(typedData);
|
|
229
|
+
expect(result).toBe(MOCK_SIGNATURE_HASH_2);
|
|
230
|
+
});
|
|
231
|
+
it("should sign a transaction", async () => {
|
|
232
|
+
const transaction = {
|
|
233
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
234
|
+
value: 1000000000000000000n,
|
|
235
|
+
};
|
|
236
|
+
const result = await provider.signTransaction(transaction);
|
|
237
|
+
expect(result).toBe(MOCK_SIGNATURE_HASH_3);
|
|
238
|
+
});
|
|
239
|
+
it("should send a transaction", async () => {
|
|
240
|
+
const transaction = {
|
|
241
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
242
|
+
value: 1000000000000000000n,
|
|
243
|
+
};
|
|
244
|
+
const result = await provider.sendTransaction(transaction);
|
|
245
|
+
expect(result).toBe(MOCK_TRANSACTION_HASH);
|
|
246
|
+
});
|
|
247
|
+
it("should get the wallet balance", async () => {
|
|
248
|
+
const balance = await provider.getBalance();
|
|
249
|
+
expect(balance).toBe(BigInt(1000000000000000000));
|
|
250
|
+
});
|
|
251
|
+
it("should wait for transaction receipt", async () => {
|
|
252
|
+
const receipt = await provider.waitForTransactionReceipt(MOCK_TRANSACTION_HASH);
|
|
253
|
+
expect(receipt).toEqual({ transactionHash: MOCK_TRANSACTION_HASH });
|
|
254
|
+
});
|
|
255
|
+
it("should read contract data", async () => {
|
|
256
|
+
const abi = [
|
|
257
|
+
{
|
|
258
|
+
name: "balanceOf",
|
|
259
|
+
type: "function",
|
|
260
|
+
inputs: [{ name: "account", type: "address" }],
|
|
261
|
+
outputs: [{ name: "balance", type: "uint256" }],
|
|
262
|
+
stateMutability: "view",
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
const params = {
|
|
266
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
267
|
+
abi,
|
|
268
|
+
functionName: "balanceOf",
|
|
269
|
+
args: [MOCK_ADDRESS],
|
|
270
|
+
};
|
|
271
|
+
const result = await provider.readContract(params);
|
|
272
|
+
expect(result).toBe("mock_result");
|
|
273
|
+
});
|
|
274
|
+
it("should transfer native tokens", async () => {
|
|
275
|
+
const result = await provider.nativeTransfer("0x1234567890123456789012345678901234567890", "1.0");
|
|
276
|
+
expect(result).toBe(MOCK_TRANSACTION_HASH);
|
|
277
|
+
});
|
|
278
|
+
it("should export wallet data", () => {
|
|
279
|
+
const exportData = provider.exportWallet();
|
|
280
|
+
expect(exportData).toEqual({
|
|
281
|
+
walletId: MOCK_WALLET_ID,
|
|
282
|
+
authorizationPrivateKey: undefined,
|
|
283
|
+
chainId: "1",
|
|
284
|
+
networkId: "ethereum-mainnet",
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
it("should handle authorization key requirements properly", async () => {
|
|
288
|
+
const authorizationKeyId = "test-auth-key-id";
|
|
289
|
+
const mockPrivyClient = {
|
|
290
|
+
walletApi: {
|
|
291
|
+
create: jest.fn().mockImplementation(({ authorizationKeyIds }) => {
|
|
292
|
+
if (authorizationKeyIds && authorizationKeyIds.length > 0) {
|
|
293
|
+
throw new Error("Missing `privy-authorization-signature` header");
|
|
294
|
+
}
|
|
295
|
+
return Promise.resolve({
|
|
296
|
+
id: "test-wallet-id",
|
|
297
|
+
address: MOCK_ADDRESS,
|
|
298
|
+
});
|
|
299
|
+
}),
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
const privyServerAuth = jest.requireMock("@privy-io/server-auth");
|
|
303
|
+
const originalMockImplementation = privyServerAuth.PrivyClient.getMockImplementation();
|
|
304
|
+
privyServerAuth.PrivyClient.mockImplementation(() => mockPrivyClient);
|
|
305
|
+
await expect(privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet({
|
|
306
|
+
appId: "test-app-id",
|
|
307
|
+
appSecret: "test-app-secret",
|
|
308
|
+
authorizationKeyId,
|
|
309
|
+
})).rejects.toThrow("authorizationPrivateKey is required when creating a new wallet with an authorizationKeyId");
|
|
310
|
+
privyServerAuth.PrivyClient.mockImplementation(originalMockImplementation);
|
|
311
|
+
});
|
|
312
|
+
it("should handle wallet creation errors", async () => {
|
|
313
|
+
const mockPrivyClient = {
|
|
314
|
+
walletApi: {
|
|
315
|
+
create: jest.fn().mockRejectedValue(new Error("API rate limit exceeded")),
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
const privyServerAuth = jest.requireMock("@privy-io/server-auth");
|
|
319
|
+
const originalMockImplementation = privyServerAuth.PrivyClient.getMockImplementation();
|
|
320
|
+
privyServerAuth.PrivyClient.mockImplementation(() => mockPrivyClient);
|
|
321
|
+
const originalConsoleError = console.error;
|
|
322
|
+
console.error = jest.fn();
|
|
323
|
+
await expect(privyEvmWalletProvider_1.PrivyEvmWalletProvider.configureWithWallet({
|
|
324
|
+
appId: "test-app-id",
|
|
325
|
+
appSecret: "test-app-secret",
|
|
326
|
+
})).rejects.toThrow("Failed to create wallet");
|
|
327
|
+
console.error = originalConsoleError;
|
|
328
|
+
privyServerAuth.PrivyClient.mockImplementation(originalMockImplementation);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
});
|
|
@@ -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) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|