Skip to content

Commit ad46f8d

Browse files
Merge branch 'main' into read-only
2 parents ffd7f87 + b7819c4 commit ad46f8d

File tree

36 files changed

+9299
-1014
lines changed

36 files changed

+9299
-1014
lines changed

packages/core/__e2e__/pushchain.spec.ts

Lines changed: 281 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { CHAIN_INFO } from '../src/lib/constants/chain';
1818
import dotenv from 'dotenv';
1919
import path from 'path';
2020
import { UniversalTxResponse } from '../src/lib/orchestrator/orchestrator.types';
21-
import { sepolia } from 'viem/chains';
21+
import { sepolia, arbitrumSepolia, baseSepolia } from 'viem/chains';
2222
import bs58 from 'bs58';
2323

2424
// Adjust path as needed if your .env is in the root
@@ -30,7 +30,7 @@ describe('PushChain (e2e)', () => {
3030
let universalSigner: UniversalSigner;
3131
let randomAccount: PrivateKeyAccount;
3232
describe('Origin - EVM (Except Push)', () => {
33-
describe(`${CHAIN.ETHEREUM_SEPOLIA}`, () => {
33+
describe('ETHEREUM_SEPOLIA', () => {
3434
const originChain = CHAIN.ETHEREUM_SEPOLIA;
3535
let pushClient: PushChain;
3636

@@ -168,6 +168,284 @@ describe('PushChain (e2e)', () => {
168168
});
169169
}, 300000);
170170
});
171+
172+
describe('ARBITRUM_SEPOLIA', () => {
173+
const originChain = CHAIN.ARBITRUM_SEPOLIA;
174+
let pushClient: PushChain;
175+
176+
beforeAll(async () => {
177+
const privateKey = process.env['EVM_PRIVATE_KEY'] as Hex;
178+
if (!privateKey) throw new Error('EVM_PRIVATE_KEY not set');
179+
180+
const account = privateKeyToAccount(privateKey);
181+
const walletClient = createWalletClient({
182+
account,
183+
transport: http(CHAIN_INFO[originChain].defaultRPC[0]),
184+
});
185+
186+
universalSigner = await PushChain.utils.signer.toUniversalFromKeypair(
187+
walletClient,
188+
{
189+
chain: originChain,
190+
library: PushChain.CONSTANTS.LIBRARY.ETHEREUM_VIEM,
191+
}
192+
);
193+
194+
pushClient = await PushChain.initialize(universalSigner, {
195+
network: pushNetwork,
196+
progressHook: (val: any) => {
197+
console.log(val);
198+
},
199+
});
200+
201+
// Generate random account
202+
randomAccount = privateKeyToAccount(generatePrivateKey());
203+
// Try to send Arbitrum Sepolia ETH to random generated address
204+
const txHash = await walletClient.sendTransaction({
205+
to: randomAccount.address,
206+
chain: arbitrumSepolia,
207+
value: PushChain.utils.helpers.parseUnits('1', 14),
208+
});
209+
const publicClient = createPublicClient({
210+
chain: arbitrumSepolia,
211+
transport: http(),
212+
});
213+
await publicClient.waitForTransactionReceipt({
214+
hash: txHash,
215+
});
216+
}, 100000);
217+
218+
it('should fail to send universal.sendTransaction with invalid feeLockTxHash', async () => {
219+
await expect(
220+
pushClient.universal.sendTransaction({
221+
to,
222+
feeLockTxHash: '0xABC', // Invalid txHash
223+
value: BigInt(1e3),
224+
})
225+
).rejects.toThrow();
226+
}, 30000);
227+
228+
it('should fail to send universal.sendTransaction with fundGas property', async () => {
229+
await expect(
230+
pushClient.universal.sendTransaction({
231+
to,
232+
value: BigInt(1e3),
233+
fundGas: {
234+
chainToken: '0x1234567890123456789012345678901234567890',
235+
},
236+
})
237+
).rejects.toThrow('Unsupported token');
238+
}, 30000);
239+
240+
it('should successfully send universal.sendTransaction without fundGas (default behavior)', async () => {
241+
const tx = await pushClient.universal.sendTransaction({
242+
to,
243+
value: BigInt(1e3),
244+
// fundGas not provided - should work fine
245+
});
246+
expect(tx).toBeDefined();
247+
expect(tx.hash).toMatch(/^0x[a-fA-F0-9]{64}$/);
248+
await txValidator(
249+
tx,
250+
pushClient.universal.origin.address as `0x${string}`,
251+
to
252+
);
253+
}, 300000);
254+
255+
it('should successfully sendTransaction - Transfer Call', async () => {
256+
const tx = await pushClient.universal.sendTransaction({
257+
to,
258+
value: BigInt(1e3),
259+
});
260+
const after = await PushChain.utils.account.convertOriginToExecutor(
261+
universalSigner.account,
262+
{
263+
onlyCompute: true,
264+
}
265+
);
266+
expect(after.deployed).toBe(true);
267+
await txValidator(
268+
tx,
269+
pushClient.universal.origin.address as `0x${string}`,
270+
to
271+
);
272+
}, 300000);
273+
274+
it('should successfully sendTransaction to funded undeployed UEA', async () => {
275+
const walletClient = createWalletClient({
276+
account: randomAccount,
277+
transport: http(CHAIN_INFO[originChain].defaultRPC[0]),
278+
});
279+
const randomUniversalSigner =
280+
await PushChain.utils.signer.toUniversalFromKeypair(walletClient, {
281+
chain: originChain,
282+
library: PushChain.CONSTANTS.LIBRARY.ETHEREUM_VIEM,
283+
});
284+
const UEA = await PushChain.utils.account.convertOriginToExecutor(
285+
randomUniversalSigner.account,
286+
{
287+
onlyCompute: true,
288+
}
289+
);
290+
291+
// Fund Undeployed UEA - 1PC
292+
await pushClient.universal.sendTransaction({
293+
to: UEA.address,
294+
value: BigInt(1e18),
295+
});
296+
297+
// Send Tx Via Random Address
298+
const randomPushClient = await PushChain.initialize(
299+
randomUniversalSigner,
300+
{
301+
network: pushNetwork,
302+
}
303+
);
304+
await randomPushClient.universal.sendTransaction({
305+
to,
306+
value: BigInt(1e6),
307+
});
308+
}, 300000);
309+
});
310+
311+
describe('BASE_SEPOLIA', () => {
312+
const originChain = CHAIN.BASE_SEPOLIA;
313+
let pushClient: PushChain;
314+
315+
beforeAll(async () => {
316+
const privateKey = process.env['EVM_PRIVATE_KEY'] as Hex;
317+
if (!privateKey) throw new Error('EVM_PRIVATE_KEY not set');
318+
319+
const account = privateKeyToAccount(privateKey);
320+
const walletClient = createWalletClient({
321+
account,
322+
transport: http(CHAIN_INFO[originChain].defaultRPC[0]),
323+
});
324+
325+
universalSigner = await PushChain.utils.signer.toUniversalFromKeypair(
326+
walletClient,
327+
{
328+
chain: originChain,
329+
library: PushChain.CONSTANTS.LIBRARY.ETHEREUM_VIEM,
330+
}
331+
);
332+
333+
pushClient = await PushChain.initialize(universalSigner, {
334+
network: pushNetwork,
335+
progressHook: (val: any) => {
336+
console.log(val);
337+
},
338+
});
339+
340+
// Generate random account
341+
randomAccount = privateKeyToAccount(generatePrivateKey());
342+
// Try to send Base Sepolia ETH to random generated address
343+
const txHash = await walletClient.sendTransaction({
344+
to: randomAccount.address,
345+
chain: baseSepolia,
346+
value: PushChain.utils.helpers.parseUnits('1', 14),
347+
});
348+
const publicClient = createPublicClient({
349+
chain: baseSepolia,
350+
transport: http(),
351+
});
352+
await publicClient.waitForTransactionReceipt({
353+
hash: txHash,
354+
});
355+
}, 100000);
356+
357+
it('should fail to send universal.sendTransaction with invalid feeLockTxHash', async () => {
358+
await expect(
359+
pushClient.universal.sendTransaction({
360+
to,
361+
feeLockTxHash: '0xABC', // Invalid txHash
362+
value: BigInt(1e3),
363+
})
364+
).rejects.toThrow();
365+
}, 30000);
366+
367+
it('should fail to send universal.sendTransaction with fundGas property', async () => {
368+
await expect(
369+
pushClient.universal.sendTransaction({
370+
to,
371+
value: BigInt(1e3),
372+
fundGas: {
373+
chainToken: '0x1234567890123456789012345678901234567890',
374+
},
375+
})
376+
).rejects.toThrow('Unsupported token');
377+
}, 30000);
378+
379+
it('should successfully send universal.sendTransaction without fundGas (default behavior)', async () => {
380+
const tx = await pushClient.universal.sendTransaction({
381+
to,
382+
value: BigInt(1e3),
383+
// fundGas not provided - should work fine
384+
});
385+
expect(tx).toBeDefined();
386+
expect(tx.hash).toMatch(/^0x[a-fA-F0-9]{64}$/);
387+
await txValidator(
388+
tx,
389+
pushClient.universal.origin.address as `0x${string}`,
390+
to
391+
);
392+
}, 300000);
393+
394+
it('should successfully sendTransaction - Transfer Call', async () => {
395+
const tx = await pushClient.universal.sendTransaction({
396+
to,
397+
value: BigInt(1e3),
398+
});
399+
const after = await PushChain.utils.account.convertOriginToExecutor(
400+
universalSigner.account,
401+
{
402+
onlyCompute: true,
403+
}
404+
);
405+
expect(after.deployed).toBe(true);
406+
await txValidator(
407+
tx,
408+
pushClient.universal.origin.address as `0x${string}`,
409+
to
410+
);
411+
}, 300000);
412+
413+
it('should successfully sendTransaction to funded undeployed UEA', async () => {
414+
const walletClient = createWalletClient({
415+
account: randomAccount,
416+
transport: http(CHAIN_INFO[originChain].defaultRPC[0]),
417+
});
418+
const randomUniversalSigner =
419+
await PushChain.utils.signer.toUniversalFromKeypair(walletClient, {
420+
chain: originChain,
421+
library: PushChain.CONSTANTS.LIBRARY.ETHEREUM_VIEM,
422+
});
423+
const UEA = await PushChain.utils.account.convertOriginToExecutor(
424+
randomUniversalSigner.account,
425+
{
426+
onlyCompute: true,
427+
}
428+
);
429+
430+
// Fund Undeployed UEA - 1PC
431+
await pushClient.universal.sendTransaction({
432+
to: UEA.address,
433+
value: BigInt(1e18),
434+
});
435+
436+
// Send Tx Via Random Address
437+
const randomPushClient = await PushChain.initialize(
438+
randomUniversalSigner,
439+
{
440+
network: pushNetwork,
441+
}
442+
);
443+
await randomPushClient.universal.sendTransaction({
444+
to,
445+
value: BigInt(1e6),
446+
});
447+
}, 300000);
448+
});
171449
});
172450
describe('Origin - Push', () => {
173451
const originChain = CHAIN.PUSH_TESTNET_DONUT;
@@ -220,7 +498,7 @@ describe('PushChain (e2e)', () => {
220498
});
221499
});
222500
describe('Origin - SVM', () => {
223-
describe(`${CHAIN.SOLANA_DEVNET}`, () => {
501+
describe('SOLANA_DEVNET', () => {
224502
const originChain = CHAIN.SOLANA_DEVNET;
225503
let pushClient: PushChain;
226504

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pushchain/core",
3-
"version": "2.0.2",
3+
"version": "2.0.20",
44
"homepage": "https://push.org",
55
"keywords": [
66
"pushchain",
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
syntax = "proto3";
2+
package uexecutor.v1;
3+
4+
import "google/api/annotations.proto";
5+
import "uexecutor/v1/types.proto";
6+
import "cosmos/base/query/v1beta1/pagination.proto";
7+
8+
option go_package = "github.com/pushchain/push-chain-node/x/uexecutor/types";
9+
10+
// Query provides defines the gRPC querier service.
11+
service Query {
12+
// Params queries all parameters of the module.
13+
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
14+
option (google.api.http).get = "/uexecutor/v1/params";
15+
}
16+
17+
// Queries all pending inbound IDs.
18+
rpc AllPendingInbounds(QueryAllPendingInboundsRequest) returns (QueryAllPendingInboundsResponse) {
19+
option (google.api.http).get = "/uexecutor/v1/pending_inbounds";
20+
}
21+
22+
// Queries a single UniversalTx by ID.
23+
rpc GetUniversalTx(QueryGetUniversalTxRequest) returns (QueryGetUniversalTxResponse) {
24+
option (google.api.http).get = "/uexecutor/v1/universal_txs/{id}";
25+
}
26+
27+
// Queries all UniversalTxs.
28+
rpc AllUniversalTx(QueryAllUniversalTxRequest) returns (QueryAllUniversalTxResponse) {
29+
option (google.api.http).get = "/uexecutor/v1/universal_txs";
30+
}
31+
}
32+
33+
// QueryParamsRequest is the request type for the Query/Params RPC method.
34+
message QueryParamsRequest {}
35+
36+
// QueryParamsResponse is the response type for the Query/Params RPC method.
37+
message QueryParamsResponse {
38+
// params defines the parameters of the module.
39+
Params params = 1;
40+
}
41+
42+
// Pending Inbounds
43+
message QueryAllPendingInboundsRequest {
44+
cosmos.base.query.v1beta1.PageRequest pagination = 1;
45+
}
46+
47+
message QueryAllPendingInboundsResponse {
48+
repeated string inbound_ids = 1;
49+
cosmos.base.query.v1beta1.PageResponse pagination = 2;
50+
}
51+
52+
// Get UniversalTx
53+
message QueryGetUniversalTxRequest {
54+
string id = 1;
55+
}
56+
57+
message QueryGetUniversalTxResponse {
58+
UniversalTx universal_tx = 1;
59+
}
60+
61+
// All UniversalTx
62+
message QueryAllUniversalTxRequest {
63+
cosmos.base.query.v1beta1.PageRequest pagination = 1;
64+
}
65+
66+
message QueryAllUniversalTxResponse {
67+
repeated UniversalTx universal_txs = 1;
68+
cosmos.base.query.v1beta1.PageResponse pagination = 2;
69+
}

0 commit comments

Comments
 (0)