@pushchain/core 6.0.19 → 6.0.21

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.
Files changed (112) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/package.json +1 -1
  3. package/src/lib/cache/cache.js +2 -0
  4. package/src/lib/constants/abi/index.d.ts +1 -0
  5. package/src/lib/constants/abi/index.js +8 -1
  6. package/src/lib/constants/abi/pc20.evm.d.ts +217 -0
  7. package/src/lib/constants/abi/pc20.evm.js +150 -0
  8. package/src/lib/constants/abi/prc20.evm.d.ts +172 -0
  9. package/src/lib/constants/abi/prc20.evm.js +97 -0
  10. package/src/lib/constants/abi/universalGatewayV0.json +1 -1
  11. package/src/lib/constants/chain.js +38 -8
  12. package/src/lib/constants/selectors.js +2 -2
  13. package/src/lib/constants/tokens.js +4 -3
  14. package/src/lib/formatters.js +16 -6
  15. package/src/lib/generated/uexecutor/v1/query.js +2 -4
  16. package/src/lib/generated/uexecutor/v1/types.d.ts +14 -0
  17. package/src/lib/generated/uexecutor/v1/types.js +90 -47
  18. package/src/lib/generated/uexecutor/v2/query.js +2 -4
  19. package/src/lib/generated/uexecutor/v2/types.d.ts +20 -0
  20. package/src/lib/generated/uexecutor/v2/types.js +49 -33
  21. package/src/lib/generated/v1/tx.js +30 -37
  22. package/src/lib/index.d.ts +4 -1
  23. package/src/lib/index.js +21 -3
  24. package/src/lib/internal/buffer.js +1 -2
  25. package/src/lib/orchestrator/cea-utils.js +73 -83
  26. package/src/lib/orchestrator/internals/account-manager.js +130 -139
  27. package/src/lib/orchestrator/internals/cascade.d.ts +0 -6
  28. package/src/lib/orchestrator/internals/cascade.js +1184 -1059
  29. package/src/lib/orchestrator/internals/confirmation.js +138 -148
  30. package/src/lib/orchestrator/internals/error-decoder.js +1 -1
  31. package/src/lib/orchestrator/internals/errors.js +12 -3
  32. package/src/lib/orchestrator/internals/execute-funds-only.d.ts +2 -2
  33. package/src/lib/orchestrator/internals/execute-funds-only.js +297 -259
  34. package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +2 -2
  35. package/src/lib/orchestrator/internals/execute-funds-payload.js +220 -220
  36. package/src/lib/orchestrator/internals/execute-standard.d.ts +0 -8
  37. package/src/lib/orchestrator/internals/execute-standard.js +339 -342
  38. package/src/lib/orchestrator/internals/gas-calculator.js +497 -520
  39. package/src/lib/orchestrator/internals/gas-usd-sizer.js +101 -110
  40. package/src/lib/orchestrator/internals/gateway-client.js +102 -103
  41. package/src/lib/orchestrator/internals/helpers.js +30 -27
  42. package/src/lib/orchestrator/internals/inbound-tracker.js +234 -238
  43. package/src/lib/orchestrator/internals/outbound-sync.js +463 -452
  44. package/src/lib/orchestrator/internals/outbound-tracker.js +27 -34
  45. package/src/lib/orchestrator/internals/payload-builder.d.ts +2 -2
  46. package/src/lib/orchestrator/internals/payload-builder.js +119 -100
  47. package/src/lib/orchestrator/internals/pc-usd-oracle.js +121 -129
  48. package/src/lib/orchestrator/internals/pc20/address-codec.d.ts +31 -0
  49. package/src/lib/orchestrator/internals/pc20/address-codec.js +124 -0
  50. package/src/lib/orchestrator/internals/pc20/chain-namespace.d.ts +68 -0
  51. package/src/lib/orchestrator/internals/pc20/chain-namespace.js +136 -0
  52. package/src/lib/orchestrator/internals/pc20/errors.d.ts +160 -0
  53. package/src/lib/orchestrator/internals/pc20/errors.js +236 -0
  54. package/src/lib/orchestrator/internals/pc20/export.d.ts +172 -0
  55. package/src/lib/orchestrator/internals/pc20/export.js +412 -0
  56. package/src/lib/orchestrator/internals/pc20/gate.d.ts +67 -0
  57. package/src/lib/orchestrator/internals/pc20/gate.js +184 -0
  58. package/src/lib/orchestrator/internals/pc20/resolver.d.ts +187 -0
  59. package/src/lib/orchestrator/internals/pc20/resolver.js +658 -0
  60. package/src/lib/orchestrator/internals/pc20/svm.d.ts +189 -0
  61. package/src/lib/orchestrator/internals/pc20/svm.js +286 -0
  62. package/src/lib/orchestrator/internals/pc20/tracking.d.ts +46 -0
  63. package/src/lib/orchestrator/internals/pc20/tracking.js +109 -0
  64. package/src/lib/orchestrator/internals/preflight.js +1 -1
  65. package/src/lib/orchestrator/internals/progress-route-hooks.js +2 -2
  66. package/src/lib/orchestrator/internals/push-chain-tx.js +319 -331
  67. package/src/lib/orchestrator/internals/quote.js +90 -94
  68. package/src/lib/orchestrator/internals/rescue.js +76 -79
  69. package/src/lib/orchestrator/internals/response-builder.d.ts +28 -1
  70. package/src/lib/orchestrator/internals/response-builder.js +817 -701
  71. package/src/lib/orchestrator/internals/route-handlers.d.ts +7 -15
  72. package/src/lib/orchestrator/internals/route-handlers.js +1512 -1178
  73. package/src/lib/orchestrator/internals/signing.js +78 -83
  74. package/src/lib/orchestrator/internals/svm-bridge.d.ts +2 -2
  75. package/src/lib/orchestrator/internals/svm-bridge.js +161 -93
  76. package/src/lib/orchestrator/internals/svm-helpers.d.ts +15 -1
  77. package/src/lib/orchestrator/internals/svm-helpers.js +68 -24
  78. package/src/lib/orchestrator/internals/svm-rent.d.ts +19 -1
  79. package/src/lib/orchestrator/internals/svm-rent.js +163 -141
  80. package/src/lib/orchestrator/internals/tx-transformer.js +26 -23
  81. package/src/lib/orchestrator/internals/uea-manager.js +89 -86
  82. package/src/lib/orchestrator/max-pc-for-gas.js +5 -6
  83. package/src/lib/orchestrator/orchestrator.js +217 -200
  84. package/src/lib/orchestrator/orchestrator.types.d.ts +121 -1
  85. package/src/lib/orchestrator/orchestrator.types.js +19 -0
  86. package/src/lib/orchestrator/payload-builders.d.ts +2 -2
  87. package/src/lib/orchestrator/payload-builders.js +26 -24
  88. package/src/lib/orchestrator/route-detector.js +26 -9
  89. package/src/lib/orchestrator/svm-idl/ix-encoder.js +1 -2
  90. package/src/lib/orchestrator/svm-idl/normalize-address.js +2 -2
  91. package/src/lib/orchestrator/svm-idl/resolve.js +1 -2
  92. package/src/lib/price-fetch/price-fetch.js +67 -68
  93. package/src/lib/progress-hook/progress-hook.js +124 -72
  94. package/src/lib/push-chain/push-chain.js +171 -153
  95. package/src/lib/push-client/push-client.js +223 -237
  96. package/src/lib/universal/account/account.js +349 -365
  97. package/src/lib/universal/signer/signer.d.ts +2 -1
  98. package/src/lib/universal/signer/signer.js +315 -299
  99. package/src/lib/universal-tx-detector/auto-detect.js +55 -60
  100. package/src/lib/universal-tx-detector/cascade.js +160 -172
  101. package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
  102. package/src/lib/universal-tx-detector/classify.js +2 -3
  103. package/src/lib/universal-tx-detector/detector-svm.js +139 -147
  104. package/src/lib/universal-tx-detector/detector.js +145 -157
  105. package/src/lib/universal-tx-detector/normalize.js +7 -7
  106. package/src/lib/utils/external-tx-hash.js +1 -2
  107. package/src/lib/utils.d.ts +44 -0
  108. package/src/lib/utils.js +762 -683
  109. package/src/lib/vm-client/evm-client.js +186 -202
  110. package/src/lib/vm-client/svm-client.d.ts +1 -1
  111. package/src/lib/vm-client/svm-client.js +220 -224
  112. package/src/lib/vm-client/vm-client.types.d.ts +14 -2
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.computeUniversalTxId = exports.__internalStatusNames = void 0;
4
4
  exports.detectUniversalTx = detectUniversalTx;
5
- const tslib_1 = require("tslib");
6
5
  /**
7
6
  * detectUniversalTx — given a source-chain tx hash + chain, fetch the receipt,
8
7
  * decode all universal-tx events, classify the tx, and (optionally) cross-
@@ -43,112 +42,107 @@ const INBOUND_KINDS = new Set([
43
42
  'INBOUND_FROM_EOA',
44
43
  'INBOUND_FROM_CEA',
45
44
  ]);
46
- function detectUniversalTx(txHash_1, chain_2) {
47
- return tslib_1.__awaiter(this, arguments, void 0, function* (txHash, chain, opts = {}) {
48
- var _a;
49
- const notes = [];
50
- const chainInfo = chain_1.CHAIN_INFO[chain];
51
- if (!chainInfo) {
52
- throw new Error(`detectUniversalTx: unknown chain ${chain}`);
53
- }
54
- if (chainInfo.vm === enums_1.VM.SVM) {
55
- return (0, normalize_1.normalizeDetectionForUser)(yield (0, detector_svm_1.detectUniversalTxSvm)(txHash, chain, opts));
56
- }
57
- if (chainInfo.vm !== enums_1.VM.EVM) {
58
- throw new Error(`detectUniversalTx: unsupported vm=${chainInfo.vm} for ${chain}`);
59
- }
60
- const rpcUrls = ((_a = opts.rpcUrls) === null || _a === void 0 ? void 0 : _a[chain]) && opts.rpcUrls[chain].length > 0
61
- ? opts.rpcUrls[chain]
62
- : chainInfo.defaultRPC.filter((r) => r && r.length > 0);
63
- if (rpcUrls.length === 0) {
64
- throw new Error(`detectUniversalTx: no RPC URL configured for chain ${chain}`);
65
- }
66
- const publicClient = (0, viem_1.createPublicClient)({
67
- transport: (0, viem_1.fallback)(rpcUrls.map((url) => (0, viem_1.http)(url))),
68
- });
69
- let receipt;
70
- try {
71
- receipt = yield publicClient.getTransactionReceipt({ hash: txHash });
72
- }
73
- catch (err) {
74
- // viem throws if the tx isn't found yet; treat as no-receipt.
75
- notes.push(`receipt fetch failed: ${err instanceof Error ? err.message : String(err)}`);
76
- return emptyDetection(txHash, chain, notes);
77
- }
78
- if (!receipt) {
79
- notes.push('no receipt returned by RPC');
80
- return emptyDetection(txHash, chain, notes);
81
- }
82
- if (receipt.status === 'reverted' && receipt.logs.length === 0) {
83
- notes.push('tx reverted with no logs');
84
- return emptyDetection(txHash, chain, notes);
85
- }
86
- const parsed = (0, viem_1.parseEventLogs)({
87
- abi: events_1.UNIVERSAL_TX_EVENT_ABI,
88
- logs: receipt.logs,
89
- strict: false,
90
- });
91
- const matchingLogs = parsed.map((p) => {
92
- var _a, _b;
93
- return ({
94
- eventName: p.eventName,
95
- address: p.address,
96
- logIndex: typeof p.logIndex ===
97
- 'bigint'
98
- ? Number(p.logIndex)
99
- : (_a = p.logIndex) !== null && _a !== void 0 ? _a : -1,
100
- args: ((_b = p.args) !== null && _b !== void 0 ? _b : {}),
101
- });
102
- });
103
- const classified = (0, classify_1.classify)(matchingLogs);
104
- notes.push(...classified.notes);
105
- const decoded = Object.assign({}, classified.decoded);
106
- // Deterministic universalTxId derivation for primary kinds whose event
107
- // doesn't carry it. Formulas from push-chain/x/uexecutor/types/keys.go:
108
- // - Inbound (any external-chain UniversalTx log):
109
- // sha256(`<caip>:<txHash>:<logIndex>`) — GetInboundUniversalTxKey:49
110
- // - Push-initiated outbound (UniversalTxOutbound on Push Chain):
111
- // sha256(`<caip>:<txHash>`) — GetPcUniversalTxKey:63
112
- if (!decoded.universalTxId) {
113
- const caip = chain; // CHAIN enum values are CAIP-2 strings.
114
- if (INBOUND_KINDS.has(classified.kind) &&
115
- classified.primaryLog &&
116
- classified.primaryLog.logIndex >= 0) {
117
- decoded.universalTxId = (0, child_inbounds_1.deriveChildUniversalTxId)(caip, txHash, classified.primaryLog.logIndex);
118
- notes.push(`universalTxId derived via sha256("${caip}:<txHash>:${classified.primaryLog.logIndex}")`);
119
- }
120
- else if (classified.kind === 'OUTBOUND_INITIATED') {
121
- decoded.universalTxId = (0, child_inbounds_1.derivePcUniversalTxId)(caip, txHash);
122
- notes.push(`universalTxId derived via sha256("${caip}:<txHash>") — pc outbound`);
123
- }
124
- }
125
- // Optional cosmos cross-reference.
126
- let pushChainTx;
127
- if (opts.pushClient &&
128
- !opts.skipPushChainLookup &&
129
- decoded.universalTxId) {
130
- pushChainTx = yield crossReferencePushChain(opts.pushClient, decoded.universalTxId, classified.kind, notes);
45
+ async function detectUniversalTx(txHash, chain, opts = {}) {
46
+ const notes = [];
47
+ const chainInfo = chain_1.CHAIN_INFO[chain];
48
+ if (!chainInfo) {
49
+ throw new Error(`detectUniversalTx: unknown chain ${chain}`);
50
+ }
51
+ if (chainInfo.vm === enums_1.VM.SVM) {
52
+ return (0, normalize_1.normalizeDetectionForUser)(await (0, detector_svm_1.detectUniversalTxSvm)(txHash, chain, opts));
53
+ }
54
+ if (chainInfo.vm !== enums_1.VM.EVM) {
55
+ throw new Error(`detectUniversalTx: unsupported vm=${chainInfo.vm} for ${chain}`);
56
+ }
57
+ const rpcUrls = opts.rpcUrls?.[chain] && opts.rpcUrls[chain].length > 0
58
+ ? opts.rpcUrls[chain]
59
+ : chainInfo.defaultRPC.filter((r) => r && r.length > 0);
60
+ if (rpcUrls.length === 0) {
61
+ throw new Error(`detectUniversalTx: no RPC URL configured for chain ${chain}`);
62
+ }
63
+ const publicClient = (0, viem_1.createPublicClient)({
64
+ transport: (0, viem_1.fallback)(rpcUrls.map((url) => (0, viem_1.http)(url))),
65
+ });
66
+ let receipt;
67
+ try {
68
+ receipt = await publicClient.getTransactionReceipt({ hash: txHash });
69
+ }
70
+ catch (err) {
71
+ // viem throws if the tx isn't found yet; treat as no-receipt.
72
+ notes.push(`receipt fetch failed: ${err instanceof Error ? err.message : String(err)}`);
73
+ return emptyDetection(txHash, chain, notes);
74
+ }
75
+ if (!receipt) {
76
+ notes.push('no receipt returned by RPC');
77
+ return emptyDetection(txHash, chain, notes);
78
+ }
79
+ if (receipt.status === 'reverted' && receipt.logs.length === 0) {
80
+ notes.push('tx reverted with no logs');
81
+ return emptyDetection(txHash, chain, notes);
82
+ }
83
+ const parsed = (0, viem_1.parseEventLogs)({
84
+ abi: events_1.UNIVERSAL_TX_EVENT_ABI,
85
+ logs: receipt.logs,
86
+ strict: false,
87
+ });
88
+ const matchingLogs = parsed.map((p) => ({
89
+ eventName: p.eventName,
90
+ address: p.address,
91
+ logIndex: typeof p.logIndex ===
92
+ 'bigint'
93
+ ? Number(p.logIndex)
94
+ : p.logIndex ?? -1,
95
+ args: (p.args ??
96
+ {}),
97
+ }));
98
+ const classified = (0, classify_1.classify)(matchingLogs);
99
+ notes.push(...classified.notes);
100
+ const decoded = { ...classified.decoded };
101
+ // Deterministic universalTxId derivation for primary kinds whose event
102
+ // doesn't carry it. Formulas from push-chain/x/uexecutor/types/keys.go:
103
+ // - Inbound (any external-chain UniversalTx log):
104
+ // sha256(`<caip>:<txHash>:<logIndex>`) — GetInboundUniversalTxKey:49
105
+ // - Push-initiated outbound (UniversalTxOutbound on Push Chain):
106
+ // sha256(`<caip>:<txHash>`) — GetPcUniversalTxKey:63
107
+ if (!decoded.universalTxId) {
108
+ const caip = chain; // CHAIN enum values are CAIP-2 strings.
109
+ if (INBOUND_KINDS.has(classified.kind) &&
110
+ classified.primaryLog &&
111
+ classified.primaryLog.logIndex >= 0) {
112
+ decoded.universalTxId = (0, child_inbounds_1.deriveChildUniversalTxId)(caip, txHash, classified.primaryLog.logIndex);
113
+ notes.push(`universalTxId derived via sha256("${caip}:<txHash>:${classified.primaryLog.logIndex}")`);
131
114
  }
132
- else if (decoded.universalTxId && !opts.pushClient) {
133
- notes.push('push cross-reference skipped (no pushClient provided)');
115
+ else if (classified.kind === 'OUTBOUND_INITIATED') {
116
+ decoded.universalTxId = (0, child_inbounds_1.derivePcUniversalTxId)(caip, txHash);
117
+ notes.push(`universalTxId derived via sha256("${caip}:<txHash>") — pc outbound`);
134
118
  }
135
- const detections = (0, classify_1.classifyAll)(classified.matchingLogs);
136
- // User-facing normalization pass: rewrites `pushChainTx.outboundHashes[n]
137
- // .externalTxHash` to base58 for SVM destinations. The raw `0x`-hex form
138
- // never leaves this function — internal consumers (findChildUtxIdFromExternalTx,
139
- // Cosmos `inbound_tx_hash=` queries) work off their own input parameters,
140
- // not the detection result's outbound summaries.
141
- return (0, normalize_1.normalizeDetectionForUser)({
142
- txHash,
143
- chain,
144
- kind: classified.kind,
145
- emitters: classified.emitters,
146
- decoded,
147
- matchingLogs: classified.matchingLogs,
148
- detections,
149
- pushChainTx,
150
- notes,
151
- });
119
+ }
120
+ // Optional cosmos cross-reference.
121
+ let pushChainTx;
122
+ if (opts.pushClient &&
123
+ !opts.skipPushChainLookup &&
124
+ decoded.universalTxId) {
125
+ pushChainTx = await crossReferencePushChain(opts.pushClient, decoded.universalTxId, classified.kind, notes);
126
+ }
127
+ else if (decoded.universalTxId && !opts.pushClient) {
128
+ notes.push('push cross-reference skipped (no pushClient provided)');
129
+ }
130
+ const detections = (0, classify_1.classifyAll)(classified.matchingLogs);
131
+ // User-facing normalization pass: rewrites `pushChainTx.outboundHashes[n]
132
+ // .externalTxHash` to base58 for SVM destinations. The raw `0x`-hex form
133
+ // never leaves this function — internal consumers (findChildUtxIdFromExternalTx,
134
+ // Cosmos `inbound_tx_hash=` queries) work off their own input parameters,
135
+ // not the detection result's outbound summaries.
136
+ return (0, normalize_1.normalizeDetectionForUser)({
137
+ txHash,
138
+ chain,
139
+ kind: classified.kind,
140
+ emitters: classified.emitters,
141
+ decoded,
142
+ matchingLogs: classified.matchingLogs,
143
+ detections,
144
+ pushChainTx,
145
+ notes,
152
146
  });
153
147
  }
154
148
  // ── Helpers ───────────────────────────────────────────────────────────
@@ -164,62 +158,56 @@ function emptyDetection(txHash, chain, notes) {
164
158
  notes,
165
159
  };
166
160
  }
167
- function crossReferencePushChain(pushClient, universalTxId, kind, notes) {
168
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
169
- var _a, _b, _c, _d;
170
- const id = universalTxId.startsWith('0x')
171
- ? universalTxId.slice(2)
172
- : universalTxId;
173
- try {
174
- const resp = yield pushClient.getUniversalTxByIdV2(id);
175
- const utx = resp === null || resp === void 0 ? void 0 : resp.universalTx;
176
- if (!utx || !utx.id) {
177
- return {
178
- id,
179
- status: 0,
180
- statusName: UNIVERSAL_TX_STATUS_NAMES[0],
181
- pcTxHashes: [],
182
- outboundHashes: [],
183
- notFound: true,
184
- };
185
- }
186
- const status = ((_a = utx.universalStatus) !== null && _a !== void 0 ? _a : 0);
187
- const statusName = (_b = UNIVERSAL_TX_STATUS_NAMES[status]) !== null && _b !== void 0 ? _b : `UNKNOWN(${status})`;
188
- const pcTxHashes = ((_c = utx.pcTx) !== null && _c !== void 0 ? _c : [])
189
- .map((p) => p === null || p === void 0 ? void 0 : p.txHash)
190
- .filter((h) => Boolean(h));
191
- const outboundHashes = ((_d = utx.outboundTx) !== null && _d !== void 0 ? _d : []).map((ob) => {
192
- var _a, _b, _c;
193
- return ({
194
- subTxId: (_a = ob.id) !== null && _a !== void 0 ? _a : '',
195
- status: outboundStatusName(ob.outboundStatus),
196
- destinationChain: (_b = ob.destinationChain) !== null && _b !== void 0 ? _b : '',
197
- externalTxHash: ((_c = ob.observedTx) === null || _c === void 0 ? void 0 : _c.txHash) || undefined,
198
- amount: ob.amount,
199
- recipient: ob.recipient,
200
- });
201
- });
202
- let stuckObservation;
203
- if (INBOUND_KINDS.has(kind)) {
204
- if (status === 0)
205
- stuckObservation = 'UNSPECIFIED';
206
- else if (status === 2 && outboundHashes.length === 0)
207
- stuckObservation = 'PENDING_INBOUND_ONLY';
208
- }
161
+ async function crossReferencePushChain(pushClient, universalTxId, kind, notes) {
162
+ const id = universalTxId.startsWith('0x')
163
+ ? universalTxId.slice(2)
164
+ : universalTxId;
165
+ try {
166
+ const resp = await pushClient.getUniversalTxByIdV2(id);
167
+ const utx = resp?.universalTx;
168
+ if (!utx || !utx.id) {
209
169
  return {
210
170
  id,
211
- status,
212
- statusName,
213
- pcTxHashes,
214
- outboundHashes,
215
- stuckObservation,
171
+ status: 0,
172
+ statusName: UNIVERSAL_TX_STATUS_NAMES[0],
173
+ pcTxHashes: [],
174
+ outboundHashes: [],
175
+ notFound: true,
216
176
  };
217
177
  }
218
- catch (err) {
219
- notes.push(`push cross-reference failed: ${err instanceof Error ? err.message : String(err)}`);
220
- return undefined;
178
+ const status = (utx.universalStatus ?? 0);
179
+ const statusName = UNIVERSAL_TX_STATUS_NAMES[status] ?? `UNKNOWN(${status})`;
180
+ const pcTxHashes = (utx.pcTx ?? [])
181
+ .map((p) => p?.txHash)
182
+ .filter((h) => Boolean(h));
183
+ const outboundHashes = (utx.outboundTx ?? []).map((ob) => ({
184
+ subTxId: ob.id ?? '',
185
+ status: outboundStatusName(ob.outboundStatus),
186
+ destinationChain: ob.destinationChain ?? '',
187
+ externalTxHash: ob.observedTx?.txHash || undefined,
188
+ amount: ob.amount,
189
+ recipient: ob.recipient,
190
+ }));
191
+ let stuckObservation;
192
+ if (INBOUND_KINDS.has(kind)) {
193
+ if (status === 0)
194
+ stuckObservation = 'UNSPECIFIED';
195
+ else if (status === 2 && outboundHashes.length === 0)
196
+ stuckObservation = 'PENDING_INBOUND_ONLY';
221
197
  }
222
- });
198
+ return {
199
+ id,
200
+ status,
201
+ statusName,
202
+ pcTxHashes,
203
+ outboundHashes,
204
+ stuckObservation,
205
+ };
206
+ }
207
+ catch (err) {
208
+ notes.push(`push cross-reference failed: ${err instanceof Error ? err.message : String(err)}`);
209
+ return undefined;
210
+ }
223
211
  }
224
212
  function outboundStatusName(n) {
225
213
  switch (n) {
@@ -232,7 +220,7 @@ function outboundStatusName(n) {
232
220
  case 3:
233
221
  return 'REVERTED';
234
222
  default:
235
- return `UNKNOWN(${n !== null && n !== void 0 ? n : '?'})`;
223
+ return `UNKNOWN(${n ?? '?'})`;
236
224
  }
237
225
  }
238
226
  exports.__internalStatusNames = UNIVERSAL_TX_STATUS_NAMES;
@@ -35,10 +35,10 @@ function normalizeOutboundSummaryForUser(s) {
35
35
  if (!s.externalTxHash)
36
36
  return s;
37
37
  const chain = (0, external_tx_hash_1.chainFromNamespace)(s.destinationChain);
38
- const next = (0, external_tx_hash_1.toExternalTxHashDisplay)(chain !== null && chain !== void 0 ? chain : undefined, s.externalTxHash);
38
+ const next = (0, external_tx_hash_1.toExternalTxHashDisplay)(chain ?? undefined, s.externalTxHash);
39
39
  if (next === s.externalTxHash)
40
40
  return s;
41
- return Object.assign(Object.assign({}, s), { externalTxHash: next });
41
+ return { ...s, externalTxHash: next };
42
42
  }
43
43
  /**
44
44
  * Normalize the outbound summaries inside `PushChainCrossRef.outboundHashes`.
@@ -56,7 +56,7 @@ function normalizeCrossRefForUser(x) {
56
56
  });
57
57
  if (!changed)
58
58
  return x;
59
- return Object.assign(Object.assign({}, x), { outboundHashes: next });
59
+ return { ...x, outboundHashes: next };
60
60
  }
61
61
  /**
62
62
  * Normalize the outbound summaries embedded in `detection.pushChainTx`.
@@ -68,7 +68,7 @@ function normalizeDetectionForUser(d) {
68
68
  const nextPushChainTx = normalizeCrossRefForUser(d.pushChainTx);
69
69
  if (nextPushChainTx === d.pushChainTx)
70
70
  return d;
71
- return Object.assign(Object.assign({}, d), { pushChainTx: nextPushChainTx });
71
+ return { ...d, pushChainTx: nextPushChainTx };
72
72
  }
73
73
  /**
74
74
  * Normalize the outbound summaries inside a `ChildInboundResolution`.
@@ -86,7 +86,7 @@ function normalizeChildInboundResolutionForUser(r) {
86
86
  });
87
87
  if (!changed)
88
88
  return r;
89
- return Object.assign(Object.assign({}, r), { outboundHashes: next });
89
+ return { ...r, outboundHashes: next };
90
90
  }
91
91
  /**
92
92
  * Type guard: identifies a `CascadeEdge.relation` as a
@@ -118,10 +118,10 @@ function normalizeCascadeNodeForUser(n) {
118
118
  if (nextRelation === edge.relation && nextNode === edge.node)
119
119
  return edge;
120
120
  childrenChanged = true;
121
- return Object.assign(Object.assign({}, edge), { relation: nextRelation, node: nextNode });
121
+ return { ...edge, relation: nextRelation, node: nextNode };
122
122
  });
123
123
  if (!childrenChanged)
124
124
  return n;
125
- return Object.assign(Object.assign({}, n), { detection: nextDetection, children: nextChildren });
125
+ return { ...n, detection: nextDetection, children: nextChildren };
126
126
  }
127
127
  //# sourceMappingURL=normalize.js.map
@@ -33,10 +33,9 @@ const bs58_1 = require("../internal/bs58");
33
33
  * inbound-tracker.ts expect the raw hex form.
34
34
  */
35
35
  function toExternalTxHashDisplay(chain, rawTxHash) {
36
- var _a;
37
36
  if (!rawTxHash)
38
37
  return rawTxHash;
39
- if (!chain || ((_a = chain_1.CHAIN_INFO[chain]) === null || _a === void 0 ? void 0 : _a.vm) !== enums_1.VM.SVM)
38
+ if (!chain || chain_1.CHAIN_INFO[chain]?.vm !== enums_1.VM.SVM)
40
39
  return rawTxHash;
41
40
  if (!rawTxHash.startsWith('0x'))
42
41
  return rawTxHash;
@@ -3,6 +3,7 @@ import { construct, toUniversal as toUniversalSigner, toUniversalFromKeypair } f
3
3
  import { CHAIN, PUSH_NETWORK } from './constants/enums';
4
4
  import { type MoveableToken } from './constants/tokens';
5
5
  import type { PushChain } from './push-chain/push-chain';
6
+ import type { PC20AddressResult } from './orchestrator/orchestrator.types';
6
7
  import type { Idl } from '@coral-xyz/anchor';
7
8
  import { registerIdl as registerSvmIdl, getRegisteredIdls as getRegisteredSvmIdls } from './orchestrator/svm-idl/registry';
8
9
  /**
@@ -285,6 +286,49 @@ export declare class Utils {
285
286
  decimals: number;
286
287
  network: PUSH_NETWORK;
287
288
  };
289
+ /**
290
+ * Resolve a PC20 token against UniversalCore's on-chain registry, and list
291
+ * every confirmed address it has across chains.
292
+ *
293
+ * Accepts either end of the mapping — an external wrapper or the canonical
294
+ * Push-native token — and always returns the canonical token at `address`,
295
+ * with every known deployment in `registry`.
296
+ *
297
+ * Unlike `getPRC20Address`, this is **asynchronous**: PC20 mappings are
298
+ * dynamic and live on chain, so there is no static table to consult. It is
299
+ * never symbol-based — identity is address-and-chain only.
300
+ *
301
+ * `chain` is optional. When omitted, the SDK works out which chain the
302
+ * address belongs to. Note the deliberate asymmetry with the transaction
303
+ * path: `funds.token` still *requires* `chain`, and sending with one that
304
+ * disagrees with where the funds actually are is rejected before any
305
+ * approval. Lookup is lenient; spending is not.
306
+ *
307
+ * @example
308
+ * ```ts
309
+ * const token = await PushChain.utils.tokens.getPC20Address('0xWrapper', {
310
+ * chain: CONSTANTS.CHAIN.ETHEREUM_SEPOLIA, // optional
311
+ * network: CONSTANTS.PUSH_NETWORK.TESTNET_DONUT,
312
+ * });
313
+ *
314
+ * token.address // '0x…' canonical Push-native PC20
315
+ * token.registry // [{ address, chain, chainName }, …]
316
+ * ```
317
+ *
318
+ * @throws {PC20WrapperNotRegisteredError} the address is unknown to the registry
319
+ * @throws {PC20RegistryMismatchError} forward/reverse registry disagreement
320
+ * @throws {PC20ExpectedButPRC20Error} a synthetic PRC20 was supplied
321
+ * @throws {PC20AmbiguousAddressError} `chain` omitted and several chains
322
+ * claim the address with different Push sources
323
+ */
324
+ getPC20Address(address: string, options: {
325
+ network: PUSH_NETWORK;
326
+ /** Where the address lives. Omit to have the SDK work it out. */
327
+ chain?: CHAIN;
328
+ rpcUrls?: Partial<Record<CHAIN, string[]>>;
329
+ /** Also run live factory-identity checks. Slower; off by default. */
330
+ strict?: boolean;
331
+ }): Promise<PC20AddressResult>;
288
332
  };
289
333
  /**
290
334
  * Internal: resolves a CHAIN enum from either a CHAIN value or a PushChain client instance.