@pushchain/core 5.1.10 → 5.1.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushchain/core",
3
- "version": "5.1.10",
3
+ "version": "5.1.12",
4
4
  "homepage": "https://push.org",
5
5
  "keywords": [
6
6
  "pushchain",
@@ -248,26 +248,33 @@ function makeToken(chain, symbol) {
248
248
  // Source of truth: SYNTHETIC_PUSH_ERC20 in ./chain.
249
249
  function buildPushChainMoveableTokenList() {
250
250
  const s = chain_1.SYNTHETIC_PUSH_ERC20[enums_1.PUSH_NETWORK.TESTNET_DONUT];
251
- const mk = (symbol, decimals, address) => ({ symbol, decimals, address, mechanism: 'approve' });
251
+ const mk = (symbol, decimals, address, sourceChain) => ({
252
+ symbol,
253
+ decimals,
254
+ address,
255
+ mechanism: 'approve',
256
+ sourceChain,
257
+ prc20Address: address,
258
+ });
252
259
  return [
253
- mk('pETH', 18, s.pETH),
254
- mk('pETH_ARB', 18, s.pETH_ARB),
255
- mk('pETH_BASE', 18, s.pETH_BASE),
256
- mk('pBNB', 18, s.pBNB),
257
- mk('pSOL', 9, s.pSOL),
258
- mk('USDT', 6, s.USDT_ETH),
259
- mk('USDT', 6, s.USDT_ARB),
260
- mk('USDT', 6, s.USDT_BASE),
261
- mk('USDT', 6, s.USDT_BNB),
262
- mk('USDT', 6, s.USDT_SOL),
263
- mk('USDC', 6, s.USDC_ETH),
264
- mk('USDC', 6, s.USDC_ARB),
265
- mk('USDC', 6, s.USDC_BASE),
266
- mk('USDC', 6, s.USDC_BNB),
267
- mk('USDC', 6, s.USDC_SOL),
268
- mk('WETH', 18, s.WETH_ETH),
269
- mk('stETH', 18, s.stETH_ETH),
270
- mk('DAI', 18, s.DAI_SOL),
260
+ mk('pETH', 18, s.pETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
261
+ mk('pETH_ARB', 18, s.pETH_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
262
+ mk('pETH_BASE', 18, s.pETH_BASE, enums_1.CHAIN.BASE_SEPOLIA),
263
+ mk('pBNB', 18, s.pBNB, enums_1.CHAIN.BNB_TESTNET),
264
+ mk('pSOL', 9, s.pSOL, enums_1.CHAIN.SOLANA_DEVNET),
265
+ mk('USDT', 6, s.USDT_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
266
+ mk('USDT', 6, s.USDT_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
267
+ mk('USDT', 6, s.USDT_BASE, enums_1.CHAIN.BASE_SEPOLIA),
268
+ mk('USDT', 6, s.USDT_BNB, enums_1.CHAIN.BNB_TESTNET),
269
+ mk('USDT', 6, s.USDT_SOL, enums_1.CHAIN.SOLANA_DEVNET),
270
+ mk('USDC', 6, s.USDC_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
271
+ mk('USDC', 6, s.USDC_ARB, enums_1.CHAIN.ARBITRUM_SEPOLIA),
272
+ mk('USDC', 6, s.USDC_BASE, enums_1.CHAIN.BASE_SEPOLIA),
273
+ mk('USDC', 6, s.USDC_BNB, enums_1.CHAIN.BNB_TESTNET),
274
+ mk('USDC', 6, s.USDC_SOL, enums_1.CHAIN.SOLANA_DEVNET),
275
+ mk('WETH', 18, s.WETH_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
276
+ mk('stETH', 18, s.stETH_ETH, enums_1.CHAIN.ETHEREUM_SEPOLIA),
277
+ mk('DAI', 18, s.DAI_SOL, enums_1.CHAIN.SOLANA_DEVNET),
271
278
  ];
272
279
  }
273
280
  // Minimal initial registries. These can be extended safely without breaking the API.
@@ -89,7 +89,7 @@ function prepareTransaction(ctx, params, callbacks) {
89
89
  // ============================================================================
90
90
  function buildHopDescriptor(ctx, params, route, ueaAddress) {
91
91
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
92
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
92
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
93
93
  // Pass 0 when user omits gasLimit → contract uses per-chain baseGasLimitByChainNamespace
94
94
  const gasLimit = (_a = params.gasLimit) !== null && _a !== void 0 ? _a : BigInt(0);
95
95
  const routeStr = route;
@@ -227,10 +227,39 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
227
227
  });
228
228
  }
229
229
  }
230
+ else if ((_f = params.funds) === null || _f === void 0 ? void 0 : _f.amount) {
231
+ // Funds-only transfer (no data, no value). Without this branch the
232
+ // CEA multicall is empty and relayed funds stay in the CEA instead
233
+ // of reaching the caller's recipient.
234
+ const token = params.funds.token;
235
+ if (token) {
236
+ if (token.mechanism === 'native') {
237
+ if (target.address.toLowerCase() !== ceaAddress.toLowerCase()) {
238
+ ceaMulticalls.push({
239
+ to: target.address,
240
+ value: params.funds.amount,
241
+ data: '0x',
242
+ });
243
+ }
244
+ }
245
+ else {
246
+ const erc20Transfer = (0, viem_1.encodeFunctionData)({
247
+ abi: erc20_evm_1.ERC20_EVM,
248
+ functionName: 'transfer',
249
+ args: [target.address, params.funds.amount],
250
+ });
251
+ ceaMulticalls.push({
252
+ to: token.address,
253
+ value: BigInt(0),
254
+ data: erc20Transfer,
255
+ });
256
+ }
257
+ }
258
+ }
230
259
  // Determine PRC-20 token and burn amount
231
260
  let prc20Token = selectors_1.ZERO_ADDRESS;
232
261
  let burnAmount = BigInt(0);
233
- if ((_f = params.funds) === null || _f === void 0 ? void 0 : _f.amount) {
262
+ if ((_g = params.funds) === null || _g === void 0 ? void 0 : _g.amount) {
234
263
  const token = params.funds.token;
235
264
  if (token) {
236
265
  prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token).address;
@@ -288,7 +317,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
288
317
  Buffer.from(ceaPda.toBytes()).toString('hex'));
289
318
  let amount = BigInt(0);
290
319
  let prc20Token;
291
- if (((_g = params.funds) === null || _g === void 0 ? void 0 : _g.amount) && params.funds.amount > BigInt(0)) {
320
+ if (((_h = params.funds) === null || _h === void 0 ? void 0 : _h.amount) && params.funds.amount > BigInt(0)) {
292
321
  amount = params.funds.amount;
293
322
  const token = params.funds.token;
294
323
  if (token && token.address) {
@@ -319,14 +348,14 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
319
348
  gasFee,
320
349
  sizing });
321
350
  }
322
- const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_h = ctx.rpcUrls[sourceChain]) === null || _h === void 0 ? void 0 : _h[0]);
351
+ const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_j = ctx.rpcUrls[sourceChain]) === null || _j === void 0 ? void 0 : _j[0]);
323
352
  // CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
324
353
  // if CEA doesn't exist yet. No SDK-side blocking needed.
325
354
  // Determine token/amount for the inbound
326
355
  let tokenAddress = selectors_1.ZERO_ADDRESS;
327
356
  let amount = BigInt(0);
328
357
  let nativeValue = BigInt(0);
329
- if ((_j = params.funds) === null || _j === void 0 ? void 0 : _j.amount) {
358
+ if ((_k = params.funds) === null || _k === void 0 ? void 0 : _k.amount) {
330
359
  const token = params.funds.token;
331
360
  if (token) {
332
361
  if (token.mechanism === 'native') {
@@ -116,7 +116,7 @@ function resolveR2Prc20TokenSvm(params, targetChain, pushNetwork, hasSvmExecute)
116
116
  * multicall when the target IS the CEA (avoids a CEA._handleMulticall revert).
117
117
  */
118
118
  function buildR2CeaPayloadEvm(params, ceaAddress, targetAddress) {
119
- var _a, _b;
119
+ var _a, _b, _c;
120
120
  if (params.migration) {
121
121
  return (0, payload_builders_1.buildMigrationPayload)();
122
122
  }
@@ -164,6 +164,38 @@ function buildR2CeaPayloadEvm(params, ceaAddress, targetAddress) {
164
164
  });
165
165
  }
166
166
  }
167
+ else if ((_c = params.funds) === null || _c === void 0 ? void 0 : _c.amount) {
168
+ // Funds-only transfer (no data, no value). Without this branch the CEA
169
+ // multicall is empty and the relayed funds sit in the CEA instead of
170
+ // being forwarded to the caller's recipient.
171
+ const token = params.funds.token;
172
+ if (token) {
173
+ if (token.mechanism === 'native') {
174
+ // Native funds (e.g. pETH → ETH): forward value to the recipient.
175
+ // Self-CEA is skipped — the gateway already deposits into the CEA.
176
+ if (targetAddress.toLowerCase() !== ceaAddress.toLowerCase()) {
177
+ ceaMulticalls.push({
178
+ to: targetAddress,
179
+ value: params.funds.amount,
180
+ data: '0x',
181
+ });
182
+ }
183
+ }
184
+ else {
185
+ // ERC-20 funds: forward via ERC20.transfer from the CEA.
186
+ const erc20Transfer = (0, viem_1.encodeFunctionData)({
187
+ abi: erc20_evm_1.ERC20_EVM,
188
+ functionName: 'transfer',
189
+ args: [targetAddress, params.funds.amount],
190
+ });
191
+ ceaMulticalls.push({
192
+ to: token.address,
193
+ value: BigInt(0),
194
+ data: erc20Transfer,
195
+ });
196
+ }
197
+ }
198
+ }
167
199
  return (0, payload_builders_1.buildCeaMulticallPayload)(ceaMulticalls);
168
200
  }
169
201
  const SIZER_HOOK_BY_ROUTE = {
@@ -212,7 +212,7 @@ function detectRoute(params) {
212
212
  * @throws ChainNotSupportedError if chain is not supported
213
213
  */
214
214
  function validateRouteParams(params, context) {
215
- var _a, _b;
215
+ var _a, _b, _c;
216
216
  const route = detectRoute(params);
217
217
  // Validate from.chain is supported external chain (Routes 3, 4)
218
218
  if ((_a = params.from) === null || _a === void 0 ? void 0 : _a.chain) {
@@ -270,11 +270,19 @@ function validateRouteParams(params, context) {
270
270
  ? `${chainEnumToName(registeredOn)}.${token.symbol}`
271
271
  : token.symbol;
272
272
  const isPushToken = registeredOn !== undefined && isPushChain(registeredOn);
273
+ // For Push-registered tokens the caller may pass a stripped clone (e.g. via
274
+ // utils.tokens.getMoveableTokens), so look up the authoritative sourceChain
275
+ // from the registry rather than trusting only the caller-supplied field.
276
+ const registrySourceChain = registeredOn
277
+ ? (tokens_1.MOVEABLE_TOKENS[registeredOn] || []).find(t => t.address.toLowerCase() === token.address.toLowerCase() &&
278
+ t.symbol === token.symbol)
279
+ : undefined;
280
+ const effectiveSourceChain = (_c = token.sourceChain) !== null && _c !== void 0 ? _c : registrySourceChain === null || registrySourceChain === void 0 ? void 0 : registrySourceChain.sourceChain;
273
281
  const validateAgainst = (chain, direction) => {
274
282
  if (isPushChain(chain))
275
283
  return;
276
284
  const ok = isPushToken
277
- ? token.sourceChain === chain
285
+ ? effectiveSourceChain === chain
278
286
  : (tokens_1.MOVEABLE_TOKENS[chain] || []).some(t => t.symbol === token.symbol);
279
287
  if (!ok) {
280
288
  throw new RouteValidationError(`Unsupported moveable token for current client and route:\n` +
@@ -8,12 +8,19 @@ const withTimestamp = (fn) => {
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
9
  return (...args) => (Object.assign(Object.assign({}, fn(...args)), { timestamp: new Date().toISOString() }));
10
10
  };
11
+ const ACRONYMS = new Set(['BNB']);
12
+ const toTitleCase = (key) => key
13
+ .split('_')
14
+ .map((part) => ACRONYMS.has(part)
15
+ ? part
16
+ : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
17
+ .join(' ');
11
18
  const friendlyChain = (chainOrNs) => {
12
- var _a;
13
19
  if (!chainOrNs)
14
20
  return 'chain';
15
21
  const asString = String(chainOrNs);
16
- return (_a = utils_1.Utils.chains.getChainName(asString)) !== null && _a !== void 0 ? _a : asString;
22
+ const key = utils_1.Utils.chains.getChainName(asString);
23
+ return key ? toTitleCase(key) : asString;
17
24
  };
18
25
  /**
19
26
  * Classify a sign-time error as either a true wallet user-decline
@@ -238,6 +238,8 @@ export declare class Utils {
238
238
  decimals: number;
239
239
  address: string;
240
240
  mechanism: "approve" | "permit2" | "native";
241
+ sourceChain?: CHAIN;
242
+ prc20Address?: `0x${string}`;
241
243
  }>;
242
244
  };
243
245
  /**
package/src/lib/utils.js CHANGED
@@ -526,37 +526,22 @@ Utils.tokens = {
526
526
  * - Otherwise returns tokens across all chains
527
527
  */
528
528
  getMoveableTokens(chainOrClient) {
529
- var _a, _b;
529
+ var _a;
530
530
  const chain = Utils.resolveChainFromInput(chainOrClient);
531
+ const map = (k, t) => {
532
+ var _a;
533
+ const extra = t;
534
+ return Object.assign(Object.assign({ chain: k, chainName: (_a = Utils.chains.getChainName(k)) !== null && _a !== void 0 ? _a : k, symbol: t.symbol, decimals: t.decimals, address: t.address, mechanism: t.mechanism }, (extra.sourceChain ? { sourceChain: extra.sourceChain } : {})), (extra.prc20Address ? { prc20Address: extra.prc20Address } : {}));
535
+ };
531
536
  if (chain) {
532
537
  const list = (_a = tokens_1.MOVEABLE_TOKENS[chain]) !== null && _a !== void 0 ? _a : [];
533
- return {
534
- tokens: list.map((t) => {
535
- var _a;
536
- return ({
537
- chain,
538
- chainName: (_a = Utils.chains.getChainName(chain)) !== null && _a !== void 0 ? _a : chain,
539
- symbol: t.symbol,
540
- decimals: t.decimals,
541
- address: t.address,
542
- mechanism: t.mechanism,
543
- });
544
- }),
545
- };
538
+ return { tokens: list.map((t) => map(chain, t)) };
546
539
  }
547
540
  const tokens = [];
548
541
  for (const [key, list] of Object.entries(tokens_1.MOVEABLE_TOKENS)) {
549
542
  const k = key;
550
- for (const t of list !== null && list !== void 0 ? list : []) {
551
- tokens.push({
552
- chain: k,
553
- chainName: (_b = Utils.chains.getChainName(k)) !== null && _b !== void 0 ? _b : k,
554
- symbol: t.symbol,
555
- decimals: t.decimals,
556
- address: t.address,
557
- mechanism: t.mechanism,
558
- });
559
- }
543
+ for (const t of list !== null && list !== void 0 ? list : [])
544
+ tokens.push(map(k, t));
560
545
  }
561
546
  return { tokens };
562
547
  },