|
1 |
| -// import 'dotenv/config'; |
2 |
| -// import { TurnkeyClient } from '@turnkey/http'; |
3 |
| -// import { |
4 |
| -// Address, |
5 |
| -// EIP1193Provider, |
6 |
| -// Index, |
7 |
| -// Quantity, |
8 |
| -// RpcTransactionRequest, |
9 |
| -// TransactionRequestEIP1559, |
10 |
| -// createWalletClient, |
11 |
| -// getAddress, |
12 |
| -// http, |
13 |
| -// numberToHex, |
14 |
| -// parseEther, |
15 |
| -// parseGwei, |
16 |
| -// recoverAddress, |
17 |
| -// serializeTransaction, |
18 |
| -// stringToHex, |
19 |
| -// } from 'viem'; |
20 |
| -// import { sepolia } from 'viem/chains'; |
21 |
| - |
22 |
| -// import { createEIP1193Provider } from '../packages/eip-1193-provider/src'; |
23 |
| -// import { createAPIKeyStamper } from '../packages/eip-1193-provider/src/turnkey'; |
| 1 | +import 'dotenv/config'; |
| 2 | + |
| 3 | +import { |
| 4 | + type Address, |
| 5 | + type EIP1193Provider, |
| 6 | + type Index, |
| 7 | + type Quantity, |
| 8 | + type RpcTransactionRequest, |
| 9 | + type TransactionRequestEIP1559, |
| 10 | + createWalletClient, |
| 11 | + getAddress, |
| 12 | + http, |
| 13 | + numberToHex, |
| 14 | + parseEther, |
| 15 | + parseGwei, |
| 16 | + recoverAddress, |
| 17 | + serializeTransaction, |
| 18 | + stringToHex, |
| 19 | +} from 'viem'; |
| 20 | + |
| 21 | +import { sepolia } from 'viem/chains'; |
| 22 | + |
| 23 | +import { beforeEach, describe, it, expect } from '@jest/globals'; |
| 24 | +import { createAPIKeyStamper, createEIP1193Provider } from '../'; |
| 25 | +import { TurnkeyClient } from '@turnkey/http'; |
| 26 | + |
24 | 27 | // import { preprocessTransaction } from '../packages/eip-1193-provider/src/utils';
|
25 | 28 | // import { createAccount } from '@turnkey/viem';
|
26 | 29 |
|
27 |
| -// const ORG_ID = process.env.ORG_ID; |
28 |
| -// const WALLET_ID = process.env.WALLET_ID; |
29 |
| -// const TURNKEY_API_PUBLIC_KEY = process.env.TURNKEY_API_PUBLIC_KEY ?? ''; |
30 |
| -// const TURNKEY_API_PRIVATE_KEY = process.env.TURNKEY_API_PRIVATE_KEY ?? ''; |
31 |
| -// const EXPECTED_WALLET_ADDRESS: Address = |
32 |
| -// '0xb9d2e69E033b3cFBa1877b86041958778E1ae919'; |
33 |
| -// const RPC_URL = 'https://sepolia.infura.io/v3/c20bd1f24c384a0484d689caff11cacd'; |
34 |
| -// const RECEIVER_ADDRESS: Address = '0x6f85Eb534E14D605d4e82bF97ddF59c18F686699'; |
35 |
| -// const TEST_TIMEOUT = 10_000; |
36 |
| - |
37 |
| -// declare module 'vitest' { |
38 |
| -// export interface TestContext { |
39 |
| -// eip1193Provider?: EIP1193Provider; |
40 |
| -// } |
41 |
| -// } |
42 |
| - |
43 |
| -// beforeEach(async (context) => { |
44 |
| -// const tk = new TurnkeyClient( |
45 |
| -// { baseUrl: 'https://api.turnkey.com' }, |
46 |
| -// await createAPIKeyStamper({ |
47 |
| -// apiPublicKey: TURNKEY_API_PUBLIC_KEY, |
48 |
| -// apiPrivateKey: TURNKEY_API_PRIVATE_KEY, |
49 |
| -// }) |
50 |
| -// ); |
51 |
| -// // extend context |
52 |
| -// context.eip1193Provider = createEIP1193Provider( |
53 |
| -// RPC_URL, |
54 |
| -// { |
55 |
| -// walletId: WALLET_ID, |
56 |
| -// organizationId: ORG_ID, |
57 |
| -// }, |
58 |
| -// tk |
59 |
| -// ); |
60 |
| -// }); |
61 |
| - |
62 |
| -// describe('eth_accounts', () => { |
63 |
| -// it("should get accounts associated with the user's wallet", async ({ |
64 |
| -// eip1193Provider, |
65 |
| -// }) => { |
66 |
| -// const accounts = await eip1193Provider?.request({ method: 'eth_accounts' }); |
67 |
| - |
68 |
| -// assert.isArray(accounts); |
69 |
| -// assert.isNotEmpty(accounts, 'accounts should be non-empty'); |
70 |
| -// expect(accounts).toContain(EXPECTED_WALLET_ADDRESS); |
71 |
| -// }); |
72 |
| -// }); |
73 |
| - |
74 |
| -// describe('eth_requestAccounts', () => { |
75 |
| -// it("should request accounts associated with the user's wallet", async ({ |
76 |
| -// eip1193Provider, |
77 |
| -// }) => { |
78 |
| -// const accounts = await eip1193Provider?.request({ |
79 |
| -// method: 'eth_requestAccounts', |
80 |
| -// }); |
| 30 | +const ORG_ID = process.env.ORG_ID; |
| 31 | +const WALLET_ID = process.env.WALLET_ID; |
| 32 | +const TURNKEY_API_PUBLIC_KEY = process.env.TURNKEY_API_PUBLIC_KEY ?? ''; |
| 33 | +const TURNKEY_API_PRIVATE_KEY = process.env.TURNKEY_API_PRIVATE_KEY ?? ''; |
| 34 | +const EXPECTED_WALLET_ADDRESS: Address = |
| 35 | + '0xb9d2e69E033b3cFBa1877b86041958778E1ae919'; |
| 36 | +const RPC_URL = 'https://sepolia.infura.io/v3/c20bd1f24c384a0484d689caff11cacd'; |
| 37 | +const RECEIVER_ADDRESS: Address = '0x6f85Eb534E14D605d4e82bF97ddF59c18F686699'; |
| 38 | +const TEST_TIMEOUT = 10_000; |
81 | 39 |
|
82 |
| -// assert.isArray(accounts); |
83 |
| -// assert.isNotEmpty(accounts, 'accounts should be non-empty'); |
84 |
| -// expect(accounts).toContain(EXPECTED_WALLET_ADDRESS); |
85 |
| -// }); |
86 |
| -// }); |
87 |
| - |
88 |
| -// describe('eth_sign/person_sign', () => { |
89 |
| -// it( |
90 |
| -// 'should sign a message', |
91 |
| -// async ({ eip1193Provider }) => { |
92 |
| -// const messageDigest = stringToHex('A man, a plan, a canal, Panama'); |
93 |
| -// const signerAddress = EXPECTED_WALLET_ADDRESS; |
94 |
| -// const signature = await eip1193Provider?.request({ |
95 |
| -// method: 'personal_sign', |
96 |
| -// params: [signerAddress, messageDigest], |
97 |
| -// }); |
98 |
| -// assert.isNotEmpty(signature, ''); |
99 |
| -// const address = await recoverAddress({ |
100 |
| -// hash: messageDigest, |
101 |
| -// signature: signature!, |
102 |
| -// }); |
103 |
| -// assert.equal(getAddress(address), getAddress(signerAddress)); |
104 |
| -// assert.match(signature!, /^0x.*$/); |
105 |
| -// }, |
106 |
| -// TEST_TIMEOUT |
107 |
| -// ); |
108 |
| -// }); |
109 |
| - |
110 |
| -// describe('eth_signTransaction', () => { |
111 |
| -// it('should sign a transaction', async ({ eip1193Provider }) => { |
112 |
| -// const from = EXPECTED_WALLET_ADDRESS; |
113 |
| -// const to = RECEIVER_ADDRESS; |
114 |
| - |
115 |
| -// const serializedTransaction = preprocessTransaction({ |
116 |
| -// from, |
117 |
| -// to, |
118 |
| -// value: numberToHex(parseEther('0.001')), |
119 |
| -// chainId: numberToHex(sepolia.id), |
120 |
| -// nonce: numberToHex(0), |
121 |
| -// gas: numberToHex(21000n), |
122 |
| -// maxFeePerGas: numberToHex(parseGwei('20')), |
123 |
| -// maxPriorityFeePerGas: numberToHex(parseGwei('2')), |
124 |
| -// type: '0x2', |
125 |
| -// } as TransactionRequestEIP1559<Quantity, Index, '0x2'>); |
126 |
| - |
127 |
| -// const signature = await eip1193Provider?.request({ |
128 |
| -// method: 'eth_signTransaction', |
129 |
| -// params: [ |
130 |
| -// { |
131 |
| -// from, |
132 |
| -// to, |
133 |
| -// value: numberToHex(parseEther('0.001')), |
134 |
| -// chainId: numberToHex(sepolia.id), |
135 |
| -// nonce: numberToHex(0), |
136 |
| -// gas: numberToHex(21000n), |
137 |
| -// maxFeePerGas: numberToHex(parseGwei('20')), |
138 |
| -// maxPriorityFeePerGas: numberToHex(parseGwei('2')), |
139 |
| -// type: '0x2', |
140 |
| -// } as TransactionRequestEIP1559<Quantity, Index, '0x2'>, |
141 |
| -// ], |
142 |
| -// }); |
| 40 | +describe('Test Turnkey EIP-1193 Provider', () => { |
| 41 | + let eip1193Provider; |
143 | 42 |
|
144 |
| -// assert.isNotEmpty(signature, ''); |
145 |
| -// assert.match(signature!, /^0x.*$/); |
146 |
| -// }); |
147 |
| -// }); |
148 |
| - |
149 |
| -// describe('eth_getBlockByNumber', () => { |
150 |
| -// it('should get blocknumber using the underlying RPC provider', async ({ |
151 |
| -// eip1193Provider, |
152 |
| -// }) => { |
153 |
| -// const blockNumber = await eip1193Provider?.request({ |
154 |
| -// method: 'eth_blockNumber', |
155 |
| -// }); |
156 |
| -// console.log(blockNumber); |
157 |
| -// assert.isNotEmpty(blockNumber, ''); |
158 |
| -// assert.match(blockNumber!, /^0x.*$/); |
159 |
| -// }); |
160 |
| -// }); |
| 43 | + beforeEach(async () => { |
| 44 | + const tk = new TurnkeyClient( |
| 45 | + { baseUrl: 'https://api.turnkey.com' }, |
| 46 | + await createAPIKeyStamper({ |
| 47 | + apiPublicKey: TURNKEY_API_PUBLIC_KEY, |
| 48 | + apiPrivateKey: TURNKEY_API_PRIVATE_KEY, |
| 49 | + }) |
| 50 | + ); |
| 51 | + |
| 52 | + eip1193Provider = await createEIP1193Provider({ |
| 53 | + rpcUrl: RPC_URL, |
| 54 | + walletId: WALLET_ID, |
| 55 | + organizationId: ORG_ID, |
| 56 | + turnkeyClient: tk, |
| 57 | + chainId: sepolia.id, |
| 58 | + }); |
| 59 | + }); |
| 60 | + |
| 61 | + describe('Supported Methods', () => { |
| 62 | + describe('EIP-1193 Wallet Methods', () => { |
| 63 | + describe('eth_accounts', () => { |
| 64 | + it("should get accounts associated with the user's wallet", async () => { |
| 65 | + const accounts = await eip1193Provider?.request({ |
| 66 | + method: 'eth_accounts', |
| 67 | + }); |
| 68 | + expect(accounts).toBeDefined(); |
| 69 | + expect(Array.isArray(accounts)).toBeTruthy(); |
| 70 | + expect(accounts.length).toBeGreaterThan(0); // Corrected line |
| 71 | + expect(accounts).toContain(EXPECTED_WALLET_ADDRESS); |
| 72 | + }); |
| 73 | + }); |
| 74 | + |
| 75 | + describe('eth_requestAccounts', () => { |
| 76 | + it("should request accounts associated with the user's wallet", async () => { |
| 77 | + const accounts = await eip1193Provider.request({ |
| 78 | + method: 'eth_requestAccounts', |
| 79 | + }); |
| 80 | + |
| 81 | + expect(accounts).toBeInstanceOf(Array); |
| 82 | + expect(accounts.length).toBeGreaterThan(0); |
| 83 | + expect(accounts).toContain(EXPECTED_WALLET_ADDRESS); |
| 84 | + }); |
| 85 | + }); |
| 86 | + |
| 87 | + describe('eth_sign/person_sign', () => { |
| 88 | + it( |
| 89 | + 'should sign a message', |
| 90 | + async () => { |
| 91 | + const messageDigest = stringToHex('A man, a plan, a canal, Panama'); |
| 92 | + const signerAddress = EXPECTED_WALLET_ADDRESS; |
| 93 | + const signature = await eip1193Provider?.request({ |
| 94 | + method: 'personal_sign', |
| 95 | + params: [signerAddress, messageDigest], |
| 96 | + }); |
| 97 | + expect(signature).toBeDefined(); |
| 98 | + expect(signature).not.toBe(''); |
| 99 | + const address = await recoverAddress({ |
| 100 | + hash: messageDigest, |
| 101 | + signature: signature!, |
| 102 | + }); |
| 103 | + expect(getAddress(address)).toBe(getAddress(signerAddress)); |
| 104 | + expect(signature).toMatch(/^0x.*$/); |
| 105 | + }, |
| 106 | + TEST_TIMEOUT |
| 107 | + ); |
| 108 | + }); |
| 109 | + |
| 110 | + describe.only('eth_signTransaction', () => { |
| 111 | + it('should sign a transaction', async () => { |
| 112 | + const from = EXPECTED_WALLET_ADDRESS; |
| 113 | + const to = RECEIVER_ADDRESS; |
| 114 | + |
| 115 | + // const serializedTransaction = preprocessTransaction({ |
| 116 | + // from, |
| 117 | + // to, |
| 118 | + // value: numberToHex(parseEther('0.001')), |
| 119 | + // chainId: numberToHex(sepolia.id), |
| 120 | + // nonce: numberToHex(0), |
| 121 | + // gas: numberToHex(21000n), |
| 122 | + // maxFeePerGas: numberToHex(parseGwei('20')), |
| 123 | + // maxPriorityFeePerGas: numberToHex(parseGwei('2')), |
| 124 | + // type: '0x2', |
| 125 | + // } as TransactionRequestEIP1559<Quantity, Index, '0x2'>); |
| 126 | + |
| 127 | + const signature = await eip1193Provider?.request({ |
| 128 | + method: 'eth_signTransaction', |
| 129 | + params: [ |
| 130 | + { |
| 131 | + from, |
| 132 | + to, |
| 133 | + value: numberToHex(parseEther('0.001')), |
| 134 | + chainId: numberToHex(sepolia.id), |
| 135 | + nonce: numberToHex(0), |
| 136 | + gas: numberToHex(21000n), |
| 137 | + maxFeePerGas: numberToHex(parseGwei('20')), |
| 138 | + maxPriorityFeePerGas: numberToHex(parseGwei('2')), |
| 139 | + type: '0x2', |
| 140 | + } as TransactionRequestEIP1559<Quantity, Index, '0x2'>, |
| 141 | + ], |
| 142 | + }); |
| 143 | + |
| 144 | + expect(signature).toBeDefined(); |
| 145 | + expect(signature).not.toBe(''); |
| 146 | + expect(signature).toMatch(/^0x.*$/); |
| 147 | + }); |
| 148 | + }); |
| 149 | + |
| 150 | + describe('eth_getBlockByNumber', () => { |
| 151 | + it('should get blocknumber using the underlying RPC provider', async () => { |
| 152 | + const blockNumber = await eip1193Provider?.request({ |
| 153 | + method: 'eth_blockNumber', |
| 154 | + }); |
| 155 | + expect(blockNumber).toBeDefined(); |
| 156 | + expect(blockNumber).not.toBe(''); |
| 157 | + expect(blockNumber).toMatch(/^0x.*$/); |
| 158 | + }); |
| 159 | + }); |
| 160 | + }); |
| 161 | + |
| 162 | + describe('Public RPC Methods', () => { |
| 163 | + describe('eth_chainId', () => { |
| 164 | + it( |
| 165 | + 'should get the correct chain id using the underlying RPC provider', |
| 166 | + async () => { |
| 167 | + const chainId = await eip1193Provider?.request({ |
| 168 | + method: 'eth_chainId', |
| 169 | + }); |
| 170 | + expect(chainId).toBeDefined(); |
| 171 | + expect(chainId).not.toBe(''); |
| 172 | + expect(chainId).toMatch(/^0x.*$/); |
| 173 | + expect(parseInt(chainId!, 16)).toBe(sepolia.id); |
| 174 | + }, |
| 175 | + TEST_TIMEOUT |
| 176 | + ); |
| 177 | + }); |
| 178 | + }); |
| 179 | + }); |
| 180 | + |
| 181 | + describe('Unsupported Methods', () => {}); |
| 182 | +}); |
161 | 183 |
|
162 |
| -// describe.only( |
| 184 | +// describe( |
163 | 185 | // 'eth_chainId',
|
164 | 186 | // () => {
|
165 | 187 | // it('should get the correct chain id using the underlying RPC provider', async ({
|
|
0 commit comments