@pushchain/core 6.0.20 → 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 (111) hide show
  1. package/CHANGELOG.md +48 -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 +3 -0
  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 -329
  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.js +306 -294
  98. package/src/lib/universal-tx-detector/auto-detect.js +55 -60
  99. package/src/lib/universal-tx-detector/cascade.js +160 -172
  100. package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
  101. package/src/lib/universal-tx-detector/classify.js +2 -3
  102. package/src/lib/universal-tx-detector/detector-svm.js +139 -147
  103. package/src/lib/universal-tx-detector/detector.js +145 -157
  104. package/src/lib/universal-tx-detector/normalize.js +7 -7
  105. package/src/lib/utils/external-tx-hash.js +1 -2
  106. package/src/lib/utils.d.ts +44 -0
  107. package/src/lib/utils.js +762 -683
  108. package/src/lib/vm-client/evm-client.js +186 -202
  109. package/src/lib/vm-client/svm-client.d.ts +1 -1
  110. package/src/lib/vm-client/svm-client.js +220 -224
  111. package/src/lib/vm-client/vm-client.types.d.ts +14 -2
@@ -9,7 +9,6 @@ exports.signUniversalPayload = signUniversalPayload;
9
9
  exports.signMigrationPayload = signMigrationPayload;
10
10
  exports.encodeUniversalPayload = encodeUniversalPayload;
11
11
  exports.encodeUniversalPayloadSvm = encodeUniversalPayloadSvm;
12
- const tslib_1 = require("tslib");
13
12
  const viem_1 = require("viem");
14
13
  const chain_1 = require("../../constants/chain");
15
14
  const enums_1 = require("../../constants/enums");
@@ -96,95 +95,91 @@ function computeMigrationHash(ctx, { verifyingContract, migrationContractAddress
96
95
  // ============================================================================
97
96
  // Payload Signing
98
97
  // ============================================================================
99
- function signUniversalPayload(ctx, universalPayload, verifyingContract, version) {
100
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
101
- const chain = ctx.universalSigner.account.chain;
102
- const { vm, chainId } = chain_1.CHAIN_INFO[chain];
103
- switch (vm) {
104
- case enums_1.VM.EVM: {
105
- if (!ctx.universalSigner.signTypedData) {
106
- throw new Error('signTypedData is not defined');
107
- }
108
- return ctx.universalSigner.signTypedData({
109
- domain: {
110
- version: version || '0.1.0',
111
- chainId: Number(chainId),
112
- verifyingContract,
113
- },
114
- types: {
115
- UniversalPayload: [
116
- { name: 'to', type: 'address' },
117
- { name: 'value', type: 'uint256' },
118
- { name: 'data', type: 'bytes' },
119
- { name: 'gasLimit', type: 'uint256' },
120
- { name: 'maxFeePerGas', type: 'uint256' },
121
- { name: 'maxPriorityFeePerGas', type: 'uint256' },
122
- { name: 'nonce', type: 'uint256' },
123
- { name: 'deadline', type: 'uint256' },
124
- { name: 'vType', type: 'uint8' },
125
- ],
126
- },
127
- primaryType: 'UniversalPayload',
128
- message: universalPayload,
129
- });
98
+ async function signUniversalPayload(ctx, universalPayload, verifyingContract, version) {
99
+ const chain = ctx.universalSigner.account.chain;
100
+ const { vm, chainId } = chain_1.CHAIN_INFO[chain];
101
+ switch (vm) {
102
+ case enums_1.VM.EVM: {
103
+ if (!ctx.universalSigner.signTypedData) {
104
+ throw new Error('signTypedData is not defined');
130
105
  }
131
- case enums_1.VM.SVM: {
132
- const digest = computeExecutionHash(ctx, {
133
- verifyingContract,
134
- payload: universalPayload,
106
+ return ctx.universalSigner.signTypedData({
107
+ domain: {
135
108
  version: version || '0.1.0',
136
- });
137
- return ctx.universalSigner.signMessage((0, viem_1.stringToBytes)(digest));
138
- }
139
- default:
140
- throw new Error(`Unsupported VM type: ${vm}`);
109
+ chainId: Number(chainId),
110
+ verifyingContract,
111
+ },
112
+ types: {
113
+ UniversalPayload: [
114
+ { name: 'to', type: 'address' },
115
+ { name: 'value', type: 'uint256' },
116
+ { name: 'data', type: 'bytes' },
117
+ { name: 'gasLimit', type: 'uint256' },
118
+ { name: 'maxFeePerGas', type: 'uint256' },
119
+ { name: 'maxPriorityFeePerGas', type: 'uint256' },
120
+ { name: 'nonce', type: 'uint256' },
121
+ { name: 'deadline', type: 'uint256' },
122
+ { name: 'vType', type: 'uint8' },
123
+ ],
124
+ },
125
+ primaryType: 'UniversalPayload',
126
+ message: universalPayload,
127
+ });
128
+ }
129
+ case enums_1.VM.SVM: {
130
+ const digest = computeExecutionHash(ctx, {
131
+ verifyingContract,
132
+ payload: universalPayload,
133
+ version: version || '0.1.0',
134
+ });
135
+ return ctx.universalSigner.signMessage((0, viem_1.stringToBytes)(digest));
141
136
  }
142
- });
137
+ default:
138
+ throw new Error(`Unsupported VM type: ${vm}`);
139
+ }
143
140
  }
144
- function signMigrationPayload(ctx_1, _a) {
145
- return tslib_1.__awaiter(this, arguments, void 0, function* (ctx, { migrationContractAddress, nonce, deadline, ueaVersion, ueaAddress, }) {
146
- const chain = ctx.universalSigner.account.chain;
147
- const { vm, chainId } = chain_1.CHAIN_INFO[chain];
148
- switch (vm) {
149
- case enums_1.VM.EVM: {
150
- if (!ctx.universalSigner.signTypedData) {
151
- throw new Error('signTypedData is not defined');
152
- }
153
- return ctx.universalSigner.signTypedData({
154
- domain: {
155
- version: ueaVersion,
156
- chainId: Number(chainId),
157
- verifyingContract: ueaAddress,
158
- },
159
- types: {
160
- MigrationPayload: [
161
- { name: 'migration', type: 'address' },
162
- { name: 'nonce', type: 'uint256' },
163
- { name: 'deadline', type: 'uint256' },
164
- ],
165
- },
166
- primaryType: 'MigrationPayload',
167
- message: {
168
- migration: migrationContractAddress,
169
- nonce: nonce.toString(),
170
- deadline: deadline.toString(),
171
- },
172
- });
141
+ async function signMigrationPayload(ctx, { migrationContractAddress, nonce, deadline, ueaVersion, ueaAddress, }) {
142
+ const chain = ctx.universalSigner.account.chain;
143
+ const { vm, chainId } = chain_1.CHAIN_INFO[chain];
144
+ switch (vm) {
145
+ case enums_1.VM.EVM: {
146
+ if (!ctx.universalSigner.signTypedData) {
147
+ throw new Error('signTypedData is not defined');
173
148
  }
174
- case enums_1.VM.SVM: {
175
- const digest = computeMigrationHash(ctx, {
176
- verifyingContract: ueaAddress,
177
- migrationContractAddress,
178
- nonce,
179
- deadline,
149
+ return ctx.universalSigner.signTypedData({
150
+ domain: {
180
151
  version: ueaVersion,
181
- });
182
- return ctx.universalSigner.signMessage((0, viem_1.stringToBytes)(digest));
183
- }
184
- default:
185
- throw new Error(`Unsupported VM type for migration: ${vm}`);
152
+ chainId: Number(chainId),
153
+ verifyingContract: ueaAddress,
154
+ },
155
+ types: {
156
+ MigrationPayload: [
157
+ { name: 'migration', type: 'address' },
158
+ { name: 'nonce', type: 'uint256' },
159
+ { name: 'deadline', type: 'uint256' },
160
+ ],
161
+ },
162
+ primaryType: 'MigrationPayload',
163
+ message: {
164
+ migration: migrationContractAddress,
165
+ nonce: nonce.toString(),
166
+ deadline: deadline.toString(),
167
+ },
168
+ });
169
+ }
170
+ case enums_1.VM.SVM: {
171
+ const digest = computeMigrationHash(ctx, {
172
+ verifyingContract: ueaAddress,
173
+ migrationContractAddress,
174
+ nonce,
175
+ deadline,
176
+ version: ueaVersion,
177
+ });
178
+ return ctx.universalSigner.signMessage((0, viem_1.stringToBytes)(digest));
186
179
  }
187
- });
180
+ default:
181
+ throw new Error(`Unsupported VM type for migration: ${vm}`);
182
+ }
188
183
  }
189
184
  // ============================================================================
190
185
  // Payload Encoding
@@ -5,14 +5,14 @@
5
5
  * Handles both native SOL and SPL token bridging with universal payload signing.
6
6
  */
7
7
  import type { UniversalPayload } from '../../generated/v1/tx';
8
- import type { ExecuteParams, UniversalTxRequest } from '../orchestrator.types';
8
+ import type { LegacyExecuteParams, UniversalTxRequest } from '../orchestrator.types';
9
9
  import type { OrchestratorContext } from './context';
10
10
  /**
11
11
  * Sends a Solana gateway transaction for the funds+payload bridge path.
12
12
  * Handles native SOL and SPL token mechanisms.
13
13
  */
14
14
  export declare function sendSVMTxWithFunds(ctx: OrchestratorContext, params: {
15
- execute: ExecuteParams;
15
+ execute: LegacyExecuteParams;
16
16
  mechanism: 'native' | 'approve' | 'permit2' | string;
17
17
  universalPayload: UniversalPayload;
18
18
  bridgeAmount: bigint;
@@ -15,6 +15,7 @@ const chain_1 = require("../../constants/chain");
15
15
  const enums_1 = require("../../constants/enums");
16
16
  const svm_client_1 = require("../../vm-client/svm-client");
17
17
  const svm_helpers_1 = require("./svm-helpers");
18
+ const svm_1 = require("./pc20/svm");
18
19
  const signing_1 = require("./signing");
19
20
  const uea_manager_1 = require("./uea-manager");
20
21
  // ============================================================================
@@ -24,99 +25,166 @@ const uea_manager_1 = require("./uea-manager");
24
25
  * Sends a Solana gateway transaction for the funds+payload bridge path.
25
26
  * Handles native SOL and SPL token mechanisms.
26
27
  */
27
- function sendSVMTxWithFunds(ctx, params) {
28
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
29
- var _a, _b;
30
- const { execute, mechanism, universalPayload, bridgeAmount, nativeAmount, req } = params;
31
- const svmClient = new svm_client_1.SvmClient({
32
- rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
33
- chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
34
- });
35
- const programId = new web3_js_1.PublicKey(universalGatewayV0_json_1.default.address);
36
- const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
37
- const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
38
- const userPk = new web3_js_1.PublicKey(ctx.universalSigner.account.address);
39
- const priceUpdatePk = new web3_js_1.PublicKey(chain_1.SVM_PYTH_PRICE_FEED);
40
- const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
41
- if (execute.payGasWith !== undefined) {
42
- throw new Error('Pay-with token is not supported on Solana');
43
- }
44
- if (!((_b = (_a = execute.funds) === null || _a === void 0 ? void 0 : _a.token) === null || _b === void 0 ? void 0 : _b.address)) {
45
- throw new Error('Token address is required for bridge path');
46
- }
47
- const isNative = mechanism === 'native' || execute.funds.token.symbol === 'SOL';
48
- const { feeVaultPda, protocolFeeLamports } = yield (0, svm_helpers_1.getSvmProtocolFee)(svmClient, programId);
49
- const ueaAddressSvm = (0, uea_manager_1.computeUEAOffchain)(ctx);
50
- const ueaVersion = yield (0, uea_manager_1.fetchUEAVersion)(ctx);
51
- const svmSignature = yield (0, signing_1.signUniversalPayload)(ctx, universalPayload, ueaAddressSvm, ueaVersion);
52
- if (isNative) {
53
- const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
54
- const nativeReq = (0, svm_helpers_1.buildSvmUniversalTxRequest)({
55
- recipient: Array.from(Buffer.alloc(20, 0)),
56
- token: web3_js_1.PublicKey.default,
57
- amount: bridgeAmount,
58
- payload: Uint8Array.from((0, signing_1.encodeUniversalPayloadSvm)(universalPayload)),
59
- revertRecipient: userPk,
60
- signatureData: svmSignature,
61
- });
62
- return yield svmClient.writeContract({
63
- abi: universalGatewayV0_json_1.default,
64
- address: programId.toBase58(),
65
- functionName: 'sendUniversalTx',
66
- args: [nativeReq, nativeAmount + protocolFeeLamports],
67
- signer: ctx.universalSigner,
68
- accounts: {
69
- config: configPda,
70
- vault: vaultPda,
71
- feeVault: feeVaultPda,
72
- userTokenAccount: vaultPda,
73
- gatewayTokenAccount: vaultPda,
74
- user: userPk,
75
- priceUpdate: priceUpdatePk,
76
- tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
77
- rateLimitConfig: rateLimitConfigPda,
78
- tokenRateLimit: tokenRateLimitPda,
79
- systemProgram: web3_js_1.SystemProgram.programId,
80
- },
81
- });
82
- }
83
- else {
84
- // Token address already validated above (line 67)
85
- const mintPk = new web3_js_1.PublicKey(execute.funds.token.address);
86
- const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
87
- const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
88
- const userAta = web3_js_1.PublicKey.findProgramAddressSync([userPk.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
89
- const vaultAta = web3_js_1.PublicKey.findProgramAddressSync([vaultPda.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
90
- const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), mintPk.toBuffer()], programId);
91
- const splReq = (0, svm_helpers_1.buildSvmUniversalTxRequest)({
92
- recipient: Array.from(Buffer.alloc(20, 0)),
93
- token: mintPk,
94
- amount: bridgeAmount,
95
- payload: Uint8Array.from((0, signing_1.encodeUniversalPayloadSvm)(universalPayload)),
96
- revertRecipient: userPk,
97
- signatureData: svmSignature,
98
- });
99
- return yield svmClient.writeContract({
100
- abi: universalGatewayV0_json_1.default,
101
- address: programId.toBase58(),
102
- functionName: 'sendUniversalTx',
103
- args: [splReq, nativeAmount + protocolFeeLamports],
104
- signer: ctx.universalSigner,
105
- accounts: {
106
- config: configPda,
107
- vault: vaultPda,
108
- feeVault: feeVaultPda,
109
- userTokenAccount: userAta,
110
- gatewayTokenAccount: vaultAta,
111
- user: userPk,
112
- priceUpdate: priceUpdatePk,
113
- tokenProgram: TOKEN_PROGRAM_ID,
114
- rateLimitConfig: rateLimitConfigPda,
115
- tokenRateLimit: tokenRateLimitPda,
116
- systemProgram: web3_js_1.SystemProgram.programId,
117
- },
118
- });
119
- }
28
+ async function sendSVMTxWithFunds(ctx, params) {
29
+ const { execute, mechanism, universalPayload, bridgeAmount, nativeAmount, req } = params;
30
+ const svmClient = new svm_client_1.SvmClient({
31
+ rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
32
+ chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
120
33
  });
34
+ const programId = new web3_js_1.PublicKey(universalGatewayV0_json_1.default.address);
35
+ const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
36
+ const [vaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('vault')], programId);
37
+ const userPk = new web3_js_1.PublicKey(ctx.universalSigner.account.address);
38
+ const priceUpdatePk = new web3_js_1.PublicKey(chain_1.SVM_PYTH_PRICE_FEED);
39
+ const [rateLimitConfigPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit_config')], programId);
40
+ if (execute.payGasWith !== undefined) {
41
+ throw new Error('Pay-with token is not supported on Solana');
42
+ }
43
+ if (!execute.funds?.token?.address) {
44
+ throw new Error('Token address is required for bridge path');
45
+ }
46
+ const isNative = mechanism === 'native' || execute.funds.token.symbol === 'SOL';
47
+ const { feeVaultPda, protocolFeeLamports } = await (0, svm_helpers_1.getSvmProtocolFee)(svmClient, programId);
48
+ const ueaAddressSvm = (0, uea_manager_1.computeUEAOffchain)(ctx);
49
+ const ueaVersion = await (0, uea_manager_1.fetchUEAVersion)(ctx);
50
+ const svmSignature = await (0, signing_1.signUniversalPayload)(ctx, universalPayload, ueaAddressSvm, ueaVersion);
51
+ // --- PC20 wrapper burn -------------------------------------------------
52
+ // route_pc20_universal_tx (deposit.rs) differs from the SPL escrow route in
53
+ // four program-enforced ways, each of which reverts if violated:
54
+ // 1. req.recipient must be the NONZERO 20-byte Push recipient — the chain
55
+ // unlocks the source token directly to it (unlockPC20), unlike SPL
56
+ // where zeros are fine because the UEA payload moves funds.
57
+ // 2. gateway_token_account must be ABSENT — the wrapper is burned via the
58
+ // mint authority, never escrowed.
59
+ // 3. remaining_accounts must be exactly [pc20_state ro, pc20_mint w].
60
+ // 4. token_rate_limit is null for a pure burn; the NATIVE-SOL rate-limit
61
+ // PDA when native value above the inbound fee rides along (that excess
62
+ // is a rate-limited native FUNDS leg).
63
+ // The SDK must NOT prepend the PC20 selector — the gateway does
64
+ // (pc20_prefixed_payload), mirroring the EVM inbound.
65
+ const pc20 = execute._pc20;
66
+ if (pc20?.direction === 'import') {
67
+ const mintPk = new web3_js_1.PublicKey(execute.funds.token.address);
68
+ const { remainingAccounts } = (0, svm_1.buildPC20BurnAccounts)({
69
+ programId,
70
+ mint: mintPk,
71
+ });
72
+ const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
73
+ const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
74
+ const userAta = web3_js_1.PublicKey.findProgramAddressSync([userPk.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
75
+ // A pure PC20 burn consumes no per-token rate limit — pass null. When
76
+ // native value rides along (nativeAmount > 0), the post-fee excess routes
77
+ // as a native FUNDS leg, which IS rate-limited: that leg requires the
78
+ // native-SOL rate-limit PDA (token_mint = Pubkey::default()) — the program
79
+ // rejects a mint-derived one (deposit.rs route_pc20_universal_tx).
80
+ const tokenRateLimit = nativeAmount > BigInt(0)
81
+ ? web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId)[0]
82
+ : null;
83
+ // The unlock recipient is ALWAYS the signer's UEA, never `execute.to`:
84
+ // the payload multicall transfers the canonical token FROM the UEA to
85
+ // `execute.to` (buildExecuteMulticall Branch 2), so the unlock must land
86
+ // on the UEA for that leg to have funds — EVM parity, and the exact shape
87
+ // the R3 drain verified live (degenerate self-transfer when to === UEA).
88
+ // Unlocking directly to `to` while the payload transfers from the UEA
89
+ // would strand the transfer leg with a zero balance.
90
+ const pushRecipient = ueaAddressSvm;
91
+ const burnReq = (0, svm_helpers_1.buildSvmUniversalTxRequest)({
92
+ recipient: Array.from(Buffer.from(pushRecipient.slice(2), 'hex')),
93
+ token: mintPk,
94
+ amount: bridgeAmount,
95
+ payload: Uint8Array.from((0, signing_1.encodeUniversalPayloadSvm)(universalPayload)),
96
+ revertRecipient: userPk,
97
+ signatureData: svmSignature,
98
+ });
99
+ return await svmClient.writeContract({
100
+ abi: universalGatewayV0_json_1.default,
101
+ address: programId.toBase58(),
102
+ functionName: 'sendUniversalTx',
103
+ args: [burnReq, nativeAmount + protocolFeeLamports],
104
+ signer: ctx.universalSigner,
105
+ accounts: {
106
+ config: configPda,
107
+ vault: vaultPda,
108
+ feeVault: feeVaultPda,
109
+ userTokenAccount: userAta,
110
+ gatewayTokenAccount: null,
111
+ user: userPk,
112
+ priceUpdate: priceUpdatePk,
113
+ tokenProgram: TOKEN_PROGRAM_ID,
114
+ rateLimitConfig: rateLimitConfigPda,
115
+ tokenRateLimit,
116
+ systemProgram: web3_js_1.SystemProgram.programId,
117
+ },
118
+ remainingAccounts,
119
+ });
120
+ }
121
+ if (isNative) {
122
+ const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), web3_js_1.PublicKey.default.toBuffer()], programId);
123
+ const nativeReq = (0, svm_helpers_1.buildSvmUniversalTxRequest)({
124
+ recipient: Array.from(Buffer.alloc(20, 0)),
125
+ token: web3_js_1.PublicKey.default,
126
+ amount: bridgeAmount,
127
+ payload: Uint8Array.from((0, signing_1.encodeUniversalPayloadSvm)(universalPayload)),
128
+ revertRecipient: userPk,
129
+ signatureData: svmSignature,
130
+ });
131
+ return await svmClient.writeContract({
132
+ abi: universalGatewayV0_json_1.default,
133
+ address: programId.toBase58(),
134
+ functionName: 'sendUniversalTx',
135
+ args: [nativeReq, nativeAmount + protocolFeeLamports],
136
+ signer: ctx.universalSigner,
137
+ accounts: {
138
+ config: configPda,
139
+ vault: vaultPda,
140
+ feeVault: feeVaultPda,
141
+ userTokenAccount: vaultPda,
142
+ gatewayTokenAccount: vaultPda,
143
+ user: userPk,
144
+ priceUpdate: priceUpdatePk,
145
+ tokenProgram: new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
146
+ rateLimitConfig: rateLimitConfigPda,
147
+ tokenRateLimit: tokenRateLimitPda,
148
+ systemProgram: web3_js_1.SystemProgram.programId,
149
+ },
150
+ });
151
+ }
152
+ else {
153
+ // Token address already validated above (line 67)
154
+ const mintPk = new web3_js_1.PublicKey(execute.funds.token.address);
155
+ const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
156
+ const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
157
+ const userAta = web3_js_1.PublicKey.findProgramAddressSync([userPk.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
158
+ const vaultAta = web3_js_1.PublicKey.findProgramAddressSync([vaultPda.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
159
+ const [tokenRateLimitPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('rate_limit'), mintPk.toBuffer()], programId);
160
+ const splReq = (0, svm_helpers_1.buildSvmUniversalTxRequest)({
161
+ recipient: Array.from(Buffer.alloc(20, 0)),
162
+ token: mintPk,
163
+ amount: bridgeAmount,
164
+ payload: Uint8Array.from((0, signing_1.encodeUniversalPayloadSvm)(universalPayload)),
165
+ revertRecipient: userPk,
166
+ signatureData: svmSignature,
167
+ });
168
+ return await svmClient.writeContract({
169
+ abi: universalGatewayV0_json_1.default,
170
+ address: programId.toBase58(),
171
+ functionName: 'sendUniversalTx',
172
+ args: [splReq, nativeAmount + protocolFeeLamports],
173
+ signer: ctx.universalSigner,
174
+ accounts: {
175
+ config: configPda,
176
+ vault: vaultPda,
177
+ feeVault: feeVaultPda,
178
+ userTokenAccount: userAta,
179
+ gatewayTokenAccount: vaultAta,
180
+ user: userPk,
181
+ priceUpdate: priceUpdatePk,
182
+ tokenProgram: TOKEN_PROGRAM_ID,
183
+ rateLimitConfig: rateLimitConfigPda,
184
+ tokenRateLimit: tokenRateLimitPda,
185
+ systemProgram: web3_js_1.SystemProgram.programId,
186
+ },
187
+ });
188
+ }
121
189
  }
122
190
  //# sourceMappingURL=svm-bridge.js.map
@@ -32,4 +32,18 @@ export declare function getSvmProtocolFee(svmClient: {
32
32
  feeVaultPda: PublicKey;
33
33
  protocolFeeLamports: bigint;
34
34
  }>;
35
- export declare function getSvmGatewayLogIndexFromTx(txResp: any): number;
35
+ /**
36
+ * Locate the gateway event whose UTX the caller should track.
37
+ *
38
+ * Default: the second gateway event when there are two (a gas leg followed by
39
+ * the funds leg), else the last one.
40
+ *
41
+ * `preferPC20` inverts that for PC20 wrapper burns. Such a transaction emits
42
+ * the PC20 burn event first and then, when native value rides along, a plain
43
+ * funds event for the gas deposit — so the default would track the deposit
44
+ * leg. A failure crediting that deposit (the known chain-side fee-credit bug)
45
+ * would then be reported as the whole transfer failing, even though the tokens
46
+ * arrived via the first event. Selection is by payload selector rather than
47
+ * position, so it survives a change in emission order.
48
+ */
49
+ export declare function getSvmGatewayLogIndexFromTx(txResp: any, preferPC20?: boolean): number;
@@ -74,30 +74,30 @@ function buildSvmUniversalTxRequestFromReq(req, revertRecipient, signatureDataOv
74
74
  amount: req.amount,
75
75
  payload: req.payload,
76
76
  revertRecipient,
77
- signatureData: signatureDataOverride !== null && signatureDataOverride !== void 0 ? signatureDataOverride : req.signatureData,
77
+ signatureData: signatureDataOverride ?? req.signatureData,
78
78
  });
79
79
  }
80
80
  // ============================================================================
81
81
  // SVM Protocol Fee
82
82
  // ============================================================================
83
- function getSvmProtocolFee(svmClient, programId) {
84
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
85
- var _a, _b, _c, _d, _e;
86
- const [feeVaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('fee_vault')], programId);
87
- try {
88
- const feeVault = yield svmClient.readContract({
89
- abi: universalGatewayV0_json_1.default,
90
- address: universalGatewayV0_json_1.default.address,
91
- functionName: 'feeVault',
92
- args: [feeVaultPda.toBase58()],
93
- });
94
- const protocolFeeLamports = BigInt((_e = (_d = ((_c = (_b = (_a = feeVault.inboundFeeLamports) !== null && _a !== void 0 ? _a : feeVault.inbound_fee_lamports) !== null && _b !== void 0 ? _b : feeVault.protocolFeeLamports) !== null && _c !== void 0 ? _c : feeVault.protocol_fee_lamports)) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '0');
95
- return { feeVaultPda, protocolFeeLamports };
96
- }
97
- catch (_f) {
98
- return { feeVaultPda, protocolFeeLamports: BigInt(0) };
99
- }
100
- });
83
+ async function getSvmProtocolFee(svmClient, programId) {
84
+ const [feeVaultPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('fee_vault')], programId);
85
+ try {
86
+ const feeVault = await svmClient.readContract({
87
+ abi: universalGatewayV0_json_1.default,
88
+ address: universalGatewayV0_json_1.default.address,
89
+ functionName: 'feeVault',
90
+ args: [feeVaultPda.toBase58()],
91
+ });
92
+ const protocolFeeLamports = BigInt((feeVault.inboundFeeLamports ??
93
+ feeVault.inbound_fee_lamports ??
94
+ feeVault.protocolFeeLamports ??
95
+ feeVault.protocol_fee_lamports)?.toString() ?? '0');
96
+ return { feeVaultPda, protocolFeeLamports };
97
+ }
98
+ catch {
99
+ return { feeVaultPda, protocolFeeLamports: BigInt(0) };
100
+ }
101
101
  }
102
102
  // ============================================================================
103
103
  // SVM Log Parsing
@@ -106,14 +106,51 @@ function getSvmProtocolFee(svmClient, programId) {
106
106
  const SVM_GATEWAY_EVENT_DISCRIMINATOR = '6c9ad829b5ea1d7c';
107
107
  // ============================================================================
108
108
  // ============================================================================
109
- function getSvmGatewayLogIndexFromTx(txResp) {
110
- var _a;
111
- const logs = (((_a = txResp === null || txResp === void 0 ? void 0 : txResp.meta) === null || _a === void 0 ? void 0 : _a.logMessages) || []);
109
+ /**
110
+ * Does this decoded `UniversalTx` event body carry a PC20-selector payload?
111
+ *
112
+ * Borsh layout after the 8-byte discriminator: sender(32) ++ recipient(20) ++
113
+ * token(32) ++ amount(8) ++ payload_len(u32 LE) ++ payload. The gateway stamps
114
+ * the `PC20` selector (ASCII, 0x50433230) on the front of the payload for a
115
+ * PC20 burn, which is what distinguishes that leg from the native funds leg
116
+ * emitted by the same transaction.
117
+ */
118
+ function isPC20EventBody(decoded) {
119
+ const PAYLOAD_LEN_OFFSET = 8 + 32 + 20 + 32 + 8;
120
+ if (decoded.length < PAYLOAD_LEN_OFFSET + 4)
121
+ return false;
122
+ const view = new DataView(decoded.buffer, decoded.byteOffset, decoded.byteLength);
123
+ const payloadLen = view.getUint32(PAYLOAD_LEN_OFFSET, true);
124
+ const start = PAYLOAD_LEN_OFFSET + 4;
125
+ if (payloadLen < 4 || decoded.length < start + 4)
126
+ return false;
127
+ return (decoded[start] === 0x50 &&
128
+ decoded[start + 1] === 0x43 &&
129
+ decoded[start + 2] === 0x32 &&
130
+ decoded[start + 3] === 0x30);
131
+ }
132
+ /**
133
+ * Locate the gateway event whose UTX the caller should track.
134
+ *
135
+ * Default: the second gateway event when there are two (a gas leg followed by
136
+ * the funds leg), else the last one.
137
+ *
138
+ * `preferPC20` inverts that for PC20 wrapper burns. Such a transaction emits
139
+ * the PC20 burn event first and then, when native value rides along, a plain
140
+ * funds event for the gas deposit — so the default would track the deposit
141
+ * leg. A failure crediting that deposit (the known chain-side fee-credit bug)
142
+ * would then be reported as the whole transfer failing, even though the tokens
143
+ * arrived via the first event. Selection is by payload selector rather than
144
+ * position, so it survives a change in emission order.
145
+ */
146
+ function getSvmGatewayLogIndexFromTx(txResp, preferPC20 = false) {
147
+ const logs = (txResp?.meta?.logMessages || []);
112
148
  if (!Array.isArray(logs) || logs.length === 0)
113
149
  return 0;
114
150
  const prefix = 'Program data: ';
115
151
  let matchCount = 0;
116
152
  let lastMatchIndex = -1;
153
+ let pc20MatchIndex = -1;
117
154
  for (let i = 0; i < logs.length; i++) {
118
155
  const log = logs[i] || '';
119
156
  if (!log.startsWith(prefix))
@@ -123,7 +160,7 @@ function getSvmGatewayLogIndexFromTx(txResp) {
123
160
  try {
124
161
  decoded = new Uint8Array(Buffer.from(base64Data, 'base64'));
125
162
  }
126
- catch (_b) {
163
+ catch {
127
164
  continue;
128
165
  }
129
166
  if (!decoded || decoded.length < 8)
@@ -132,10 +169,17 @@ function getSvmGatewayLogIndexFromTx(txResp) {
132
169
  if (discriminatorHex === SVM_GATEWAY_EVENT_DISCRIMINATOR) {
133
170
  matchCount++;
134
171
  lastMatchIndex = i;
135
- if (matchCount === 2)
172
+ if (preferPC20 && pc20MatchIndex === -1 && isPC20EventBody(decoded)) {
173
+ pc20MatchIndex = i;
174
+ }
175
+ // Default selection returns eagerly on the second event; when looking
176
+ // for the PC20 leg the scan must continue so ordering cannot matter.
177
+ if (!preferPC20 && matchCount === 2)
136
178
  return i;
137
179
  }
138
180
  }
181
+ if (preferPC20 && pc20MatchIndex !== -1)
182
+ return pc20MatchIndex;
139
183
  if (lastMatchIndex !== -1)
140
184
  return lastMatchIndex;
141
185
  return 0;