@pushchain/core 0.1.17 → 0.1.18
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 +11 -226
- package/package.json +1 -1
- package/src/lib/constants/abi/factoryV1.d.ts +15 -16
- package/src/lib/constants/abi/factoryV1.js +276 -193
- package/src/lib/constants/abi/factoryV1.js.map +1 -1
- package/src/lib/constants/abi/feeLocker.evm.d.ts +22 -22
- package/src/lib/constants/abi/feeLocker.evm.js +273 -229
- package/src/lib/constants/abi/feeLocker.evm.js.map +1 -1
- package/src/lib/constants/abi/index.d.ts +2 -2
- package/src/lib/constants/abi/index.js +5 -5
- package/src/lib/constants/abi/index.js.map +1 -1
- package/src/lib/constants/abi/{smartAccount.evm.d.ts → uea.evm.d.ts} +15 -22
- package/src/lib/constants/abi/{smartAccount.evm.js → uea.evm.js} +49 -59
- package/src/lib/constants/abi/uea.evm.js.map +1 -0
- package/src/lib/constants/abi/{smartAccount.svm.d.ts → uea.svm.d.ts} +15 -22
- package/src/lib/constants/abi/{smartAccount.svm.js → uea.svm.js} +49 -59
- package/src/lib/constants/abi/uea.svm.js.map +1 -0
- package/src/lib/constants/chain.js +7 -7
- package/src/lib/constants/chain.js.map +1 -1
- package/src/lib/constants/index.d.ts +0 -1
- package/src/lib/constants/viem-push-testnet.d.ts +0 -1
- package/src/lib/generated/v1/tx.d.ts +44 -31
- package/src/lib/generated/v1/tx.js +120 -157
- package/src/lib/generated/v1/tx.js.map +1 -1
- package/src/lib/orchestrator/orchestrator.d.ts +28 -21
- package/src/lib/orchestrator/orchestrator.js +170 -218
- package/src/lib/orchestrator/orchestrator.js.map +1 -1
- package/src/lib/orchestrator/orchestrator.types.d.ts +1 -1
- package/src/lib/price-fetch/price-fetch.js +23 -13
- package/src/lib/price-fetch/price-fetch.js.map +1 -1
- package/src/lib/push-client/push-client.d.ts +10 -3
- package/src/lib/push-client/push-client.js +25 -6
- package/src/lib/push-client/push-client.js.map +1 -1
- package/src/lib/pushChain.d.ts +28 -13
- package/src/lib/pushChain.js +33 -9
- package/src/lib/pushChain.js.map +1 -1
- package/src/lib/universal/account/account.js +3 -11
- package/src/lib/universal/account/account.js.map +1 -1
- package/src/lib/vm-client/svm-client.js +1 -1
- package/src/lib/vm-client/svm-client.js.map +1 -1
- package/src/lib/constants/abi/smartAccount.evm.js.map +0 -1
- package/src/lib/constants/abi/smartAccount.svm.js.map +0 -1
|
@@ -14,7 +14,6 @@ const anchor = tslib_1.__importStar(require("@coral-xyz/anchor"));
|
|
|
14
14
|
const tx_1 = require("../generated/v1/tx");
|
|
15
15
|
const price_fetch_1 = require("../price-fetch/price-fetch");
|
|
16
16
|
const bytes_1 = require("@coral-xyz/anchor/dist/cjs/utils/bytes");
|
|
17
|
-
const ethers_1 = require("ethers");
|
|
18
17
|
class Orchestrator {
|
|
19
18
|
constructor(universalSigner, pushNetwork, rpcUrls = {}, printTraces = false) {
|
|
20
19
|
this.universalSigner = universalSigner;
|
|
@@ -43,146 +42,94 @@ class Orchestrator {
|
|
|
43
42
|
execute(execute) {
|
|
44
43
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
45
44
|
const chain = this.universalSigner.account.chain;
|
|
46
|
-
|
|
47
|
-
execute.data = '0x';
|
|
48
|
-
}
|
|
49
|
-
if (this.printTraces) {
|
|
50
|
-
console.log(`[${this.constructor.name}] Starting cross-chain execution from chain: ${chain}`);
|
|
51
|
-
}
|
|
52
|
-
// Add validation that if sepolia, or any origin testnet, you can only interact with Push testnet. Same for mainnet
|
|
53
|
-
const isTestnet = [
|
|
54
|
-
enums_1.CHAIN.ETHEREUM_SEPOLIA,
|
|
55
|
-
enums_1.CHAIN.SOLANA_TESTNET,
|
|
56
|
-
enums_1.CHAIN.SOLANA_DEVNET,
|
|
57
|
-
].includes(chain);
|
|
58
|
-
const isMainnet = [enums_1.CHAIN.ETHEREUM_MAINNET, enums_1.CHAIN.SOLANA_MAINNET].includes(chain);
|
|
59
|
-
if (isTestnet &&
|
|
60
|
-
this.pushClient.pushChainInfo.chainId !==
|
|
61
|
-
chain_1.CHAIN_INFO[enums_1.CHAIN.PUSH_TESTNET_DONUT].chainId &&
|
|
62
|
-
this.pushClient.pushChainInfo.chainId !==
|
|
63
|
-
chain_1.CHAIN_INFO[enums_1.CHAIN.PUSH_LOCALNET].chainId) {
|
|
64
|
-
throw new Error('Testnet chains can only interact with Push Testnet or Localnet');
|
|
65
|
-
}
|
|
66
|
-
if (isMainnet &&
|
|
67
|
-
this.pushClient.pushChainInfo.chainId !==
|
|
68
|
-
chain_1.CHAIN_INFO[enums_1.CHAIN.PUSH_MAINNET].chainId) {
|
|
69
|
-
throw new Error('Mainnet chains can only interact with Push Mainnet');
|
|
70
|
-
}
|
|
45
|
+
this.validateMainnetConnection(chain);
|
|
71
46
|
// 1. Execute direct tx if signer is already on Push Chain
|
|
72
47
|
if (this.isPushChain(chain)) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
48
|
+
this.printLog('Push to Push Transaction Detected');
|
|
49
|
+
const txHash = yield this.pushClient.sendTransaction({
|
|
50
|
+
to: execute.to,
|
|
51
|
+
data: execute.data || '0x',
|
|
76
52
|
value: execute.value,
|
|
77
53
|
signer: this.universalSigner,
|
|
78
54
|
});
|
|
55
|
+
if (chain === enums_1.CHAIN.PUSH_LOCALNET) {
|
|
56
|
+
// @dev - Required for preventing cosmos fetching failures
|
|
57
|
+
const delay = (ms) => {
|
|
58
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
59
|
+
};
|
|
60
|
+
yield delay(3000);
|
|
61
|
+
}
|
|
62
|
+
return this.pushClient.getCosmosTx(txHash);
|
|
79
63
|
}
|
|
80
|
-
// 2. Get Push chain
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
const { address: nmscAddress, deployed: isNMSCDeployed } = yield this.getNMSCAddress();
|
|
85
|
-
if (this.printTraces) {
|
|
86
|
-
console.log(`[${this.constructor.name}] NMSC Address: ${nmscAddress}`);
|
|
87
|
-
console.log(`[${this.constructor.name}] Deployed: ${isNMSCDeployed}`);
|
|
88
|
-
}
|
|
64
|
+
// 2. Get Push chain UEA address for this signer
|
|
65
|
+
this.printLog('Fetching UEA for Connected Universal Account');
|
|
66
|
+
const { address: UEA, deployed: isUEADeployed } = yield this.computeUEA();
|
|
67
|
+
this.printLog(`UEA: ${UEA}, Deployed: ${isUEADeployed}`);
|
|
89
68
|
// 3. Estimate funds required for the execution
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
98
|
-
if (this.printTraces) {
|
|
99
|
-
console.log(`[${this.constructor.name}] GasEstimate: ${gasEstimate}`);
|
|
100
|
-
}
|
|
69
|
+
this.printLog('Estimating Gas Limit for Execution');
|
|
70
|
+
// const gasEstimate = await this.pushClient.estimateGas({
|
|
71
|
+
// to: execute.target,
|
|
72
|
+
// data: execute.data,
|
|
73
|
+
// // value: execute.value, @DEV - taking 0 as of now
|
|
74
|
+
// });
|
|
75
|
+
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
76
|
+
this.printLog(`GasEstimate: ${gasEstimate}`);
|
|
101
77
|
// Fetch current gas price
|
|
102
|
-
|
|
103
|
-
console.log(`[${this.constructor.name}] Fetching Gas Price`);
|
|
104
|
-
}
|
|
78
|
+
this.printLog('Fetching Gas Price');
|
|
105
79
|
const gasPrice = yield this.pushClient.getGasPrice();
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
// Add 10% buffer as integer math
|
|
110
|
-
if (this.printTraces) {
|
|
111
|
-
console.log(`[${this.constructor.name}] Calculating estimated gas fee for execution`);
|
|
112
|
-
}
|
|
113
|
-
const requiredGasFee = (gasEstimate * gasPrice * BigInt(110)) / BigInt(100);
|
|
114
|
-
if (this.printTraces) {
|
|
115
|
-
console.log(`[${this.constructor.name}] Required Gas Fee: ${requiredGasFee}`);
|
|
116
|
-
}
|
|
117
|
-
// Total funds = gas fee + value being sent
|
|
80
|
+
this.printLog(`Gas Price: ${gasPrice}`);
|
|
81
|
+
const requiredGasFee = gasEstimate * gasPrice;
|
|
82
|
+
this.printLog(`Required Gas Fee for Execution: ${requiredGasFee} upc`);
|
|
118
83
|
const requiredFunds = requiredGasFee + execute.value;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const nonce = isNMSCDeployed
|
|
129
|
-
? yield this.getNMSCNonce(nmscAddress)
|
|
130
|
-
: BigInt(0);
|
|
84
|
+
this.printLog(`Total Required Funds for Execution (fee + value): ${requiredFunds} upc`);
|
|
85
|
+
// 4. Check UEA balance on Push Chain
|
|
86
|
+
this.printLog('Checking UEA balance');
|
|
87
|
+
const funds = yield this.pushClient.getBalance(UEA);
|
|
88
|
+
this.printLog(`Current balance: ${funds}`);
|
|
89
|
+
// 5. Get UEA Nonce
|
|
90
|
+
this.printLog('Fetching UEA nonce');
|
|
91
|
+
const nonce = isUEADeployed ? yield this.getUEANonce(UEA) : BigInt(0);
|
|
92
|
+
this.printLog(`Current Nonce: ${nonce}`);
|
|
131
93
|
// 6. Create execution hash ( execution data to be signed )
|
|
132
|
-
const
|
|
133
|
-
|
|
94
|
+
const universalPayload = {
|
|
95
|
+
to: execute.to,
|
|
134
96
|
value: execute.value,
|
|
135
|
-
data: execute.data,
|
|
136
|
-
gasLimit: execute.gasLimit || BigInt(
|
|
97
|
+
data: execute.data || '0x',
|
|
98
|
+
gasLimit: execute.gasLimit || BigInt(1e7),
|
|
137
99
|
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
138
|
-
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(
|
|
100
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
139
101
|
nonce,
|
|
140
102
|
deadline: execute.deadline || BigInt(9999999999),
|
|
103
|
+
sigType: tx_1.SignatureType.signedVerification,
|
|
141
104
|
};
|
|
142
105
|
const executionHash = this.computeExecutionHash({
|
|
143
|
-
verifyingContract:
|
|
144
|
-
payload:
|
|
106
|
+
verifyingContract: UEA,
|
|
107
|
+
payload: universalPayload,
|
|
145
108
|
});
|
|
146
|
-
|
|
147
|
-
console.log(`[${this.constructor.name}] Execution hash: ${executionHash}`);
|
|
148
|
-
}
|
|
109
|
+
this.printLog(`Universal Payload Hash: ${executionHash}`);
|
|
149
110
|
// 7. If not enough funds, lock required fee on source chain and send tx to Push chain
|
|
150
111
|
let feeLockTxHash = execute.feeLockTxHash;
|
|
151
112
|
if (funds < requiredFunds && !feeLockTxHash) {
|
|
152
|
-
if (this.printTraces) {
|
|
153
|
-
console.log(`[${this.constructor.name}] Insufficient funds, locking additional fees...`);
|
|
154
|
-
}
|
|
155
113
|
const fundDifference = requiredFunds - funds;
|
|
114
|
+
this.printLog(`Insufficient funds, locking funds ${fundDifference} upc`);
|
|
156
115
|
const fundDifferenceInUSDC = this.pushClient.pushToUSDC(fundDifference); // ( USDC with 8 decimal points )
|
|
157
116
|
feeLockTxHash = yield this.lockFee(fundDifferenceInUSDC, executionHash);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
if (this.printTraces) {
|
|
162
|
-
console.log(`[${this.constructor.name}] Waiting for Block Confirmations..`);
|
|
163
|
-
}
|
|
117
|
+
this.printLog(`Fee lock TxHash: ${feeLockTxHash}`);
|
|
118
|
+
this.printLog('Waiting for Block Confirmations of Fee lock Tx on Origin Chain');
|
|
164
119
|
yield this.waitForLockerFeeConfirmation(feeLockTxHash);
|
|
165
|
-
|
|
166
|
-
console.log(`[${this.constructor.name}] Enough Origin Chain Block confirmations received`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (this.printTraces) {
|
|
170
|
-
console.log(`[${this.constructor.name}] Signing execution data...`);
|
|
120
|
+
this.printLog('Enough Confirmations received');
|
|
171
121
|
}
|
|
172
122
|
// 8. Sign execution data
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
console.log(`[${this.constructor.name}] Transaction sent successfully. Hash: ${txHash}`);
|
|
184
|
-
}
|
|
185
|
-
return txHash;
|
|
123
|
+
this.printLog(`Signing Universal Payload`);
|
|
124
|
+
const signature = yield this.signUniversalPayload(universalPayload, UEA);
|
|
125
|
+
this.printLog(`Signature: ${(0, viem_1.bytesToHex)(signature)}`);
|
|
126
|
+
// 9. Send Tx to Push chain
|
|
127
|
+
this.printLog('Sending transaction to Push chain');
|
|
128
|
+
// Serialize & parse in one go to convert all bigint → string
|
|
129
|
+
const serializedPayload = JSON.parse(JSON.stringify(universalPayload, this.bigintReplacer));
|
|
130
|
+
const tx = yield this.sendUniversalTx(isUEADeployed, feeLockTxHash, serializedPayload, signature);
|
|
131
|
+
this.printLog(`Tx: ${JSON.stringify(tx, this.bigintReplacer, 2)}`);
|
|
132
|
+
return tx;
|
|
186
133
|
});
|
|
187
134
|
}
|
|
188
135
|
/**
|
|
@@ -224,7 +171,7 @@ class Orchestrator {
|
|
|
224
171
|
nativeAmount =
|
|
225
172
|
(amount * BigInt(Math.pow(10, nativeDecimals))) / nativeTokenUsdPrice;
|
|
226
173
|
const svmClient = new svm_client_1.SvmClient({ rpcUrls });
|
|
227
|
-
const [lockerPda
|
|
174
|
+
const [lockerPda] = anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('locker')], new web3_js_1.PublicKey(lockerContract));
|
|
228
175
|
return yield svmClient.writeContract({
|
|
229
176
|
abi: abi_1.FEE_LOCKER_SVM,
|
|
230
177
|
address: lockerContract,
|
|
@@ -244,7 +191,7 @@ class Orchestrator {
|
|
|
244
191
|
}
|
|
245
192
|
});
|
|
246
193
|
}
|
|
247
|
-
|
|
194
|
+
signUniversalPayload(universalPayload, verifyingContract, version) {
|
|
248
195
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
249
196
|
const chain = this.universalSigner.account.chain;
|
|
250
197
|
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
@@ -260,8 +207,8 @@ class Orchestrator {
|
|
|
260
207
|
verifyingContract,
|
|
261
208
|
},
|
|
262
209
|
types: {
|
|
263
|
-
|
|
264
|
-
{ name: '
|
|
210
|
+
UniversalPayload: [
|
|
211
|
+
{ name: 'to', type: 'address' },
|
|
265
212
|
{ name: 'value', type: 'uint256' },
|
|
266
213
|
{ name: 'data', type: 'bytes' },
|
|
267
214
|
{ name: 'gasLimit', type: 'uint256' },
|
|
@@ -269,17 +216,18 @@ class Orchestrator {
|
|
|
269
216
|
{ name: 'maxPriorityFeePerGas', type: 'uint256' },
|
|
270
217
|
{ name: 'nonce', type: 'uint256' },
|
|
271
218
|
{ name: 'deadline', type: 'uint256' },
|
|
219
|
+
{ name: 'sigType', type: 'uint8' },
|
|
272
220
|
],
|
|
273
221
|
},
|
|
274
|
-
primaryType: '
|
|
275
|
-
message:
|
|
222
|
+
primaryType: 'UniversalPayload',
|
|
223
|
+
message: universalPayload,
|
|
276
224
|
});
|
|
277
225
|
}
|
|
278
226
|
case enums_1.VM.SVM: {
|
|
279
227
|
const digest = this.computeExecutionHash({
|
|
280
228
|
chainId: Number(this.pushClient.pushChainInfo.chainId),
|
|
281
229
|
verifyingContract,
|
|
282
|
-
payload:
|
|
230
|
+
payload: universalPayload,
|
|
283
231
|
version: version || '0.1.0',
|
|
284
232
|
});
|
|
285
233
|
return this.universalSigner.signMessage((0, viem_1.stringToBytes)(digest));
|
|
@@ -293,89 +241,69 @@ class Orchestrator {
|
|
|
293
241
|
/**
|
|
294
242
|
* Sends a custom Cosmos tx to Push Chain (gasless) to execute user intent.
|
|
295
243
|
*/
|
|
296
|
-
|
|
244
|
+
sendUniversalTx(isUEADeployed, feeLockTxHash, universalPayload, signature) {
|
|
297
245
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
298
246
|
const { chain, address } = this.universalSigner.account;
|
|
299
|
-
const { vm
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
ownerKey: vm === enums_1.VM.EVM
|
|
247
|
+
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
248
|
+
const universalAccount = {
|
|
249
|
+
chain,
|
|
250
|
+
owner: vm === enums_1.VM.EVM
|
|
304
251
|
? address
|
|
305
252
|
: vm === enums_1.VM.SVM
|
|
306
253
|
? (0, viem_1.bytesToHex)(bytes_1.bs58.decode(address))
|
|
307
254
|
: address,
|
|
308
|
-
vmType: tx_1.vmType[vm],
|
|
309
255
|
};
|
|
310
256
|
const { cosmosAddress: signer } = this.pushClient.getSignerAddress();
|
|
311
257
|
const msgs = [];
|
|
312
|
-
if (!
|
|
258
|
+
if (!isUEADeployed) {
|
|
313
259
|
/**
|
|
314
|
-
* @dev - fee should be locked for
|
|
260
|
+
* @dev - fee should be locked for UEA deployment to avoid spamming
|
|
315
261
|
*/
|
|
316
262
|
if (!feeLockTxHash) {
|
|
317
|
-
throw new Error('
|
|
263
|
+
throw new Error('UEA cannot be deployed without fee locking');
|
|
318
264
|
}
|
|
319
|
-
msgs.push(this.pushClient.
|
|
265
|
+
msgs.push(this.pushClient.createMsgDeployUEA({
|
|
320
266
|
signer,
|
|
321
|
-
|
|
267
|
+
universalAccount,
|
|
322
268
|
txHash: feeLockTxHash,
|
|
323
269
|
}));
|
|
324
270
|
}
|
|
325
271
|
if (feeLockTxHash) {
|
|
326
|
-
msgs.push(this.pushClient.
|
|
272
|
+
msgs.push(this.pushClient.createMsgMintPC({
|
|
327
273
|
signer,
|
|
328
|
-
|
|
274
|
+
universalAccount,
|
|
329
275
|
txHash: feeLockTxHash,
|
|
330
276
|
}));
|
|
331
277
|
}
|
|
332
|
-
if (
|
|
278
|
+
if (universalPayload && signature) {
|
|
333
279
|
msgs.push(this.pushClient.createMsgExecutePayload({
|
|
334
280
|
signer,
|
|
335
|
-
|
|
336
|
-
|
|
281
|
+
universalAccount,
|
|
282
|
+
universalPayload,
|
|
337
283
|
signature: (0, viem_1.bytesToHex)(signature),
|
|
338
284
|
}));
|
|
339
285
|
}
|
|
340
286
|
const txBody = yield this.pushClient.createCosmosTxBody(msgs);
|
|
341
287
|
const txRaw = yield this.pushClient.signCosmosTx(txBody);
|
|
342
|
-
|
|
343
|
-
if (txresponse.code === 0) {
|
|
344
|
-
return txresponse.transactionHash;
|
|
345
|
-
}
|
|
346
|
-
else {
|
|
347
|
-
throw new Error(txresponse.rawLog);
|
|
348
|
-
}
|
|
288
|
+
return this.pushClient.broadcastCosmosTx(txRaw);
|
|
349
289
|
});
|
|
350
290
|
}
|
|
351
291
|
/**
|
|
352
|
-
*
|
|
353
|
-
* Used to differentiate logic for Push-native interactions vs external chains.
|
|
354
|
-
*
|
|
355
|
-
* @param chain - The chain identifier (e.g., PUSH_MAINNET, PUSH_TESTNET_DONUT)
|
|
356
|
-
* @returns True if the chain is a Push chain, false otherwise.
|
|
357
|
-
*/
|
|
358
|
-
isPushChain(chain) {
|
|
359
|
-
return (chain === enums_1.CHAIN.PUSH_MAINNET ||
|
|
360
|
-
chain === enums_1.CHAIN.PUSH_TESTNET_DONUT ||
|
|
361
|
-
chain === enums_1.CHAIN.PUSH_LOCALNET);
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Computes the EIP-712 digest hash for the CrossChainPayload structure.
|
|
292
|
+
* Computes the EIP-712 digest hash for the UniversalPayload structure.
|
|
365
293
|
* This is the message that should be signed by the user's wallet (e.g., Solana signer).
|
|
366
294
|
*
|
|
367
295
|
* The resulting hash is equivalent to:
|
|
368
296
|
* keccak256("\x19\x01" || domainSeparator || structHash)
|
|
369
297
|
*
|
|
370
298
|
* @param chainId - EVM chain ID of the destination chain (Push Chain)
|
|
371
|
-
* @param verifyingContract - Address of the verifying contract (i.e., the user's
|
|
299
|
+
* @param verifyingContract - Address of the verifying contract (i.e., the user's UEA smart wallet)
|
|
372
300
|
* @param version - Optional EIP-712 domain version (default: '0.1.0')
|
|
373
|
-
* @param payload - Execution details encoded into the
|
|
301
|
+
* @param payload - Execution details encoded into the UniversalPayload struct
|
|
374
302
|
* @returns keccak256 digest to be signed by the user
|
|
375
303
|
*/
|
|
376
304
|
computeExecutionHash({ chainId = Number(this.pushClient.pushChainInfo.chainId), verifyingContract, payload, version = '0.1.0', }) {
|
|
377
|
-
// 1.
|
|
378
|
-
const typeHash = (0, viem_1.keccak256)((0, viem_1.toBytes)('
|
|
305
|
+
// 1. Type hash
|
|
306
|
+
const typeHash = (0, viem_1.keccak256)((0, viem_1.toBytes)('UniversalPayload(address to,uint256 value,bytes data,uint256 gasLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 nonce,uint256 deadline,uint8 sigType)'));
|
|
379
307
|
// 2. Domain separator
|
|
380
308
|
const domainTypeHash = (0, viem_1.keccak256)((0, viem_1.toBytes)('EIP712Domain(string version,uint256 chainId,address verifyingContract)'));
|
|
381
309
|
const domainSeparator = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([
|
|
@@ -392,7 +320,7 @@ class Orchestrator {
|
|
|
392
320
|
// 3. Struct hash
|
|
393
321
|
const structHash = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([
|
|
394
322
|
{ name: 'typeHash', type: 'bytes32' },
|
|
395
|
-
{ name: '
|
|
323
|
+
{ name: 'to', type: 'address' },
|
|
396
324
|
{ name: 'value', type: 'uint256' },
|
|
397
325
|
{ name: 'dataHash', type: 'bytes32' },
|
|
398
326
|
{ name: 'gasLimit', type: 'uint256' },
|
|
@@ -400,9 +328,10 @@ class Orchestrator {
|
|
|
400
328
|
{ name: 'maxPriorityFeePerGas', type: 'uint256' },
|
|
401
329
|
{ name: 'nonce', type: 'uint256' },
|
|
402
330
|
{ name: 'deadline', type: 'uint256' },
|
|
331
|
+
{ name: 'sigType', type: 'uint8' },
|
|
403
332
|
], [
|
|
404
333
|
typeHash,
|
|
405
|
-
payload.
|
|
334
|
+
payload.to,
|
|
406
335
|
payload.value,
|
|
407
336
|
(0, viem_1.keccak256)(payload.data),
|
|
408
337
|
payload.gasLimit,
|
|
@@ -410,49 +339,41 @@ class Orchestrator {
|
|
|
410
339
|
payload.maxPriorityFeePerGas,
|
|
411
340
|
payload.nonce,
|
|
412
341
|
payload.deadline,
|
|
342
|
+
payload.sigType,
|
|
413
343
|
]));
|
|
414
|
-
// 4. Final digest
|
|
415
|
-
|
|
416
|
-
return digest;
|
|
344
|
+
// 4. Final digest
|
|
345
|
+
return (0, viem_1.keccak256)((0, viem_1.encodePacked)(['string', 'bytes32', 'bytes32'], ['\x19\x01', domainSeparator, structHash]));
|
|
417
346
|
}
|
|
418
347
|
/**
|
|
419
|
-
* Computes
|
|
348
|
+
* Computes UEA for given UniversalAccount
|
|
349
|
+
* @dev - This fn calls a view fn of Factory Contract
|
|
350
|
+
* @returns UEA Address with Deployment Status
|
|
420
351
|
*/
|
|
421
|
-
|
|
422
|
-
// TODO: CREATE ANOTHER FUNCTION TO CHECK IF NMSC IS DEPLOYED.
|
|
423
|
-
getNMSCAddress() {
|
|
352
|
+
computeUEA() {
|
|
424
353
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
425
354
|
const { chain, address } = this.universalSigner.account;
|
|
426
|
-
const { vm
|
|
355
|
+
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
427
356
|
if (this.isPushChain(chain)) {
|
|
428
|
-
throw new Error('
|
|
357
|
+
throw new Error('UEA cannot be computed for a Push Chain Address');
|
|
429
358
|
}
|
|
430
359
|
const computedAddress = yield this.pushClient.readContract({
|
|
431
360
|
address: this.pushClient.pushChainInfo.factoryAddress,
|
|
432
361
|
abi: abi_1.FACTORY_V1,
|
|
433
|
-
functionName: '
|
|
362
|
+
functionName: 'computeUEA',
|
|
434
363
|
args: [
|
|
435
364
|
{
|
|
436
|
-
|
|
437
|
-
chainId,
|
|
365
|
+
chain,
|
|
438
366
|
/**
|
|
439
|
-
* @dev -
|
|
367
|
+
* @dev - Owner should be in bytes
|
|
440
368
|
* for eth - convert hex to bytes
|
|
441
369
|
* for sol - convert base64 to bytes
|
|
442
370
|
* for others - not defined yet
|
|
443
371
|
*/
|
|
444
|
-
|
|
372
|
+
owner: vm === enums_1.VM.EVM
|
|
445
373
|
? address
|
|
446
374
|
: vm === enums_1.VM.SVM
|
|
447
375
|
? (0, viem_1.bytesToHex)(bytes_1.bs58.decode(address))
|
|
448
376
|
: address,
|
|
449
|
-
/**
|
|
450
|
-
* @dev
|
|
451
|
-
* 0 -> evm
|
|
452
|
-
* 1 -> svm
|
|
453
|
-
* Rest are not defined
|
|
454
|
-
*/
|
|
455
|
-
vmType: vm === enums_1.VM.EVM ? 0 : vm === enums_1.VM.SVM ? 1 : 2,
|
|
456
377
|
},
|
|
457
378
|
],
|
|
458
379
|
});
|
|
@@ -462,57 +383,55 @@ class Orchestrator {
|
|
|
462
383
|
return { address: computedAddress, deployed: byteCode !== undefined };
|
|
463
384
|
});
|
|
464
385
|
}
|
|
465
|
-
|
|
466
|
-
calculateUEAOffchain() {
|
|
386
|
+
computeUEAOffchain() {
|
|
467
387
|
const { chain, address } = this.universalSigner.account;
|
|
468
|
-
const {
|
|
388
|
+
const { implementationAddress } = chain_1.CHAIN_INFO[chain];
|
|
389
|
+
// If already an on-chain Push EOA, just return it
|
|
469
390
|
if (this.isPushChain(chain)) {
|
|
470
391
|
return address;
|
|
471
392
|
}
|
|
393
|
+
// 1) Figure out the external‐chain ownerKey bytes
|
|
472
394
|
let ownerKey;
|
|
473
|
-
if (vm === enums_1.VM.EVM) {
|
|
395
|
+
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.EVM) {
|
|
474
396
|
ownerKey = address;
|
|
475
397
|
}
|
|
476
|
-
else if (vm === enums_1.VM.SVM) {
|
|
398
|
+
else if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
|
|
477
399
|
ownerKey = (0, viem_1.bytesToHex)(bytes_1.bs58.decode(address));
|
|
478
400
|
}
|
|
479
401
|
else {
|
|
480
|
-
throw new Error(`Unsupported VM type: ${vm}`);
|
|
402
|
+
throw new Error(`Unsupported VM type: ${chain_1.CHAIN_INFO[chain].vm}`);
|
|
481
403
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
accountId.chainId,
|
|
494
|
-
accountId.ownerKey,
|
|
495
|
-
accountId.vmType,
|
|
496
|
-
],
|
|
497
|
-
]);
|
|
498
|
-
const salt = ethers_1.ethers.keccak256(encodedAccountId);
|
|
404
|
+
// Step 1: Recreate the salt: keccak256(abi.encode(UniversalAccount))
|
|
405
|
+
const encodedAccountId = (0, viem_1.encodeAbiParameters)([
|
|
406
|
+
{
|
|
407
|
+
type: 'tuple',
|
|
408
|
+
components: [
|
|
409
|
+
{ name: 'chain', type: 'string' },
|
|
410
|
+
{ name: 'owner', type: 'bytes' },
|
|
411
|
+
],
|
|
412
|
+
},
|
|
413
|
+
], [{ chain, owner: ownerKey }]);
|
|
414
|
+
const salt = (0, viem_1.keccak256)(encodedAccountId);
|
|
499
415
|
// Step 2: Clone Minimal Proxy bytecode
|
|
500
|
-
const minimalProxyRuntimeCode = '0x3d602d80600a3d3981f3' +
|
|
416
|
+
const minimalProxyRuntimeCode = ('0x3d602d80600a3d3981f3' +
|
|
501
417
|
'363d3d373d3d3d363d73' +
|
|
502
418
|
implementationAddress.toLowerCase().replace(/^0x/, '') +
|
|
503
|
-
'5af43d82803e903d91602b57fd5bf3';
|
|
419
|
+
'5af43d82803e903d91602b57fd5bf3');
|
|
504
420
|
// Step 3: Get init code hash (used by CREATE2)
|
|
505
|
-
const initCodeHash =
|
|
421
|
+
const initCodeHash = (0, viem_1.keccak256)(minimalProxyRuntimeCode);
|
|
506
422
|
// Step 4: Predict the address using standard CREATE2 formula
|
|
507
|
-
|
|
508
|
-
|
|
423
|
+
return (0, viem_1.getCreate2Address)({
|
|
424
|
+
from: this.pushClient.pushChainInfo.factoryAddress,
|
|
425
|
+
salt,
|
|
426
|
+
bytecodeHash: initCodeHash,
|
|
427
|
+
});
|
|
509
428
|
}
|
|
510
429
|
/**
|
|
511
430
|
* @dev - Although as of now nonce var is same in evm & svm so switch conditions does not matter
|
|
512
|
-
* @param address
|
|
513
|
-
* @returns
|
|
431
|
+
* @param address UEA address
|
|
432
|
+
* @returns UEA current nonce
|
|
514
433
|
*/
|
|
515
|
-
|
|
434
|
+
getUEANonce(address) {
|
|
516
435
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
517
436
|
const chain = this.universalSigner.account.chain;
|
|
518
437
|
const { vm } = chain_1.CHAIN_INFO[chain];
|
|
@@ -520,14 +439,14 @@ class Orchestrator {
|
|
|
520
439
|
case enums_1.VM.EVM: {
|
|
521
440
|
return this.pushClient.readContract({
|
|
522
441
|
address,
|
|
523
|
-
abi: abi_1.
|
|
442
|
+
abi: abi_1.UEA_EVM,
|
|
524
443
|
functionName: 'nonce',
|
|
525
444
|
});
|
|
526
445
|
}
|
|
527
446
|
case enums_1.VM.SVM: {
|
|
528
447
|
return this.pushClient.readContract({
|
|
529
448
|
address,
|
|
530
|
-
abi: abi_1.
|
|
449
|
+
abi: abi_1.UEA_SVM,
|
|
531
450
|
functionName: 'nonce',
|
|
532
451
|
});
|
|
533
452
|
}
|
|
@@ -537,6 +456,7 @@ class Orchestrator {
|
|
|
537
456
|
}
|
|
538
457
|
});
|
|
539
458
|
}
|
|
459
|
+
// TODO: Fix this fn - It needs to get UOA for a given UEA
|
|
540
460
|
getUOA() {
|
|
541
461
|
return {
|
|
542
462
|
chain: this.universalSigner.account.chain,
|
|
@@ -566,6 +486,38 @@ class Orchestrator {
|
|
|
566
486
|
}
|
|
567
487
|
});
|
|
568
488
|
}
|
|
489
|
+
/********************************** HELPER FUNCTIONS **************************************************/
|
|
490
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
491
|
+
bigintReplacer(_key, value) {
|
|
492
|
+
return typeof value === 'bigint'
|
|
493
|
+
? value.toString() // convert BigInt to string
|
|
494
|
+
: value;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Checks if the given chain belongs to the Push Chain ecosystem.
|
|
498
|
+
* Used to differentiate logic for Push-native interactions vs external chains.
|
|
499
|
+
*
|
|
500
|
+
* @param chain - The chain identifier (e.g., PUSH_MAINNET, PUSH_TESTNET_DONUT)
|
|
501
|
+
* @returns True if the chain is a Push chain, false otherwise.
|
|
502
|
+
*/
|
|
503
|
+
isPushChain(chain) {
|
|
504
|
+
return (chain === enums_1.CHAIN.PUSH_MAINNET ||
|
|
505
|
+
chain === enums_1.CHAIN.PUSH_TESTNET_DONUT ||
|
|
506
|
+
chain === enums_1.CHAIN.PUSH_LOCALNET);
|
|
507
|
+
}
|
|
508
|
+
validateMainnetConnection(chain) {
|
|
509
|
+
const isMainnet = [enums_1.CHAIN.ETHEREUM_MAINNET, enums_1.CHAIN.SOLANA_MAINNET].includes(chain);
|
|
510
|
+
if (isMainnet &&
|
|
511
|
+
this.pushClient.pushChainInfo.chainId !==
|
|
512
|
+
chain_1.CHAIN_INFO[enums_1.CHAIN.PUSH_MAINNET].chainId) {
|
|
513
|
+
throw new Error('Mainnet chains can only interact with Push Mainnet');
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
printLog(log) {
|
|
517
|
+
if (this.printTraces) {
|
|
518
|
+
console.log(`[${this.constructor.name}] ${log}`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
569
521
|
}
|
|
570
522
|
exports.Orchestrator = Orchestrator;
|
|
571
523
|
//# sourceMappingURL=orchestrator.js.map
|