@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
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SvmClient = void 0;
4
- const tslib_1 = require("tslib");
5
4
  const web3_js_1 = require("@solana/web3.js");
6
5
  const anchor_1 = require("@coral-xyz/anchor");
7
6
  const bs58_1 = require("../internal/bs58");
@@ -11,8 +10,9 @@ const ALT_ADDRESS = new web3_js_1.PublicKey('EWXJ1ERkMwizmSovjtQ2qBTDpm1vxrZZ4Y2
11
10
  * Solana-compatible VM client for reading and writing SVM-based chains.
12
11
  */
13
12
  class SvmClient {
13
+ connections;
14
+ currentConnectionIndex = 0;
14
15
  constructor({ rpcUrls }) {
15
- this.currentConnectionIndex = 0;
16
16
  if (!rpcUrls || rpcUrls.length === 0) {
17
17
  throw new Error('At least one RPC URL must be provided');
18
18
  }
@@ -21,35 +21,33 @@ class SvmClient {
21
21
  /**
22
22
  * Executes a function with automatic fallback to next RPC endpoint on failure
23
23
  */
24
- executeWithFallback(operation_1) {
25
- return tslib_1.__awaiter(this, arguments, void 0, function* (operation, operationName = 'operation') {
26
- let lastError = null;
27
- // Try each connection starting from current index
28
- for (let attempt = 0; attempt < this.connections.length; attempt++) {
29
- const connectionIndex = (this.currentConnectionIndex + attempt) % this.connections.length;
30
- const connection = this.connections[connectionIndex];
31
- try {
32
- const result = yield operation(connection);
33
- // Success - update current connection index if we switched
34
- if (connectionIndex !== this.currentConnectionIndex) {
35
- //console.log(`Switched to RPC endpoint ${connectionIndex + 1}: ${this.rpcUrls[connectionIndex]}`);
36
- this.currentConnectionIndex = connectionIndex;
37
- }
38
- return result;
24
+ async executeWithFallback(operation, operationName = 'operation') {
25
+ let lastError = null;
26
+ // Try each connection starting from current index
27
+ for (let attempt = 0; attempt < this.connections.length; attempt++) {
28
+ const connectionIndex = (this.currentConnectionIndex + attempt) % this.connections.length;
29
+ const connection = this.connections[connectionIndex];
30
+ try {
31
+ const result = await operation(connection);
32
+ // Success - update current connection index if we switched
33
+ if (connectionIndex !== this.currentConnectionIndex) {
34
+ //console.log(`Switched to RPC endpoint ${connectionIndex + 1}: ${this.rpcUrls[connectionIndex]}`);
35
+ this.currentConnectionIndex = connectionIndex;
39
36
  }
40
- catch (error) {
41
- lastError = error;
42
- //console.warn(`RPC endpoint ${connectionIndex + 1} failed for ${operationName}:`, error);
43
- // If this was our last attempt, throw the error
44
- if (attempt === this.connections.length - 1) {
45
- break;
46
- }
47
- // Wait a bit before trying next endpoint
48
- yield new Promise((resolve) => setTimeout(resolve, 100));
37
+ return result;
38
+ }
39
+ catch (error) {
40
+ lastError = error;
41
+ //console.warn(`RPC endpoint ${connectionIndex + 1} failed for ${operationName}:`, error);
42
+ // If this was our last attempt, throw the error
43
+ if (attempt === this.connections.length - 1) {
44
+ break;
49
45
  }
46
+ // Wait a bit before trying next endpoint
47
+ await new Promise((resolve) => setTimeout(resolve, 100));
50
48
  }
51
- throw new Error(`All RPC endpoints failed for ${operationName}. Last error: ${lastError === null || lastError === void 0 ? void 0 : lastError.message}`);
52
- });
49
+ }
50
+ throw new Error(`All RPC endpoints failed for ${operationName}. Last error: ${lastError?.message}`);
53
51
  }
54
52
  /** Build an AnchorProvider; if a signer is passed we wrap it, otherwise we give a no-op wallet. */
55
53
  createProvider(connection, signer) {
@@ -59,8 +57,8 @@ class SvmClient {
59
57
  wallet = {
60
58
  publicKey: feePayerPk,
61
59
  payer: signer.account,
62
- signTransaction: (tx) => tslib_1.__awaiter(this, void 0, void 0, function* () { return tx; }),
63
- signAllTransactions: (txs) => tslib_1.__awaiter(this, void 0, void 0, function* () { return txs; }),
60
+ signTransaction: async (tx) => tx,
61
+ signAllTransactions: async (txs) => txs,
64
62
  };
65
63
  }
66
64
  else {
@@ -69,8 +67,8 @@ class SvmClient {
69
67
  wallet = {
70
68
  publicKey: kp.publicKey,
71
69
  payer: kp,
72
- signTransaction: (tx) => tslib_1.__awaiter(this, void 0, void 0, function* () { return tx; }),
73
- signAllTransactions: (txs) => tslib_1.__awaiter(this, void 0, void 0, function* () { return txs; }),
70
+ signTransaction: async (tx) => tx,
71
+ signAllTransactions: async (txs) => txs,
74
72
  };
75
73
  }
76
74
  return new anchor_1.AnchorProvider(connection, wallet, {
@@ -80,227 +78,225 @@ class SvmClient {
80
78
  /**
81
79
  * Returns the balance (in lamports) of a Solana address.
82
80
  */
83
- getBalance(address) {
84
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
85
- const pubkey = new web3_js_1.PublicKey(address);
86
- const lamports = yield this.executeWithFallback((connection) => connection.getBalance(pubkey), 'getBalance');
87
- return BigInt(lamports);
88
- });
81
+ async getBalance(address) {
82
+ const pubkey = new web3_js_1.PublicKey(address);
83
+ const lamports = await this.executeWithFallback((connection) => connection.getBalance(pubkey), 'getBalance');
84
+ return BigInt(lamports);
89
85
  }
90
86
  /**
91
87
  * Reads a full program account using Anchor IDL.
92
88
  * `functionName` must match the account layout name in the IDL.
93
89
  */
94
- readContract(_a) {
95
- return tslib_1.__awaiter(this, arguments, void 0, function* ({ abi, functionName, args = [], }) {
96
- return this.executeWithFallback((connection) => tslib_1.__awaiter(this, void 0, void 0, function* () {
97
- const provider = this.createProvider(connection);
98
- // Anchor v0.31 constructor no longer takes programId
99
- // Use the IDL's embedded metadata.address instead
100
- const program = new anchor_1.Program(abi, provider);
101
- const pubkey = new web3_js_1.PublicKey(args[0]);
102
- // Cast account namespace to any to allow dynamic string
103
- const accountNamespace = program.account;
104
- const account = yield accountNamespace[functionName].fetch(pubkey);
105
- return account;
106
- }), 'readContract');
107
- });
90
+ async readContract({ abi, functionName, args = [], }) {
91
+ return this.executeWithFallback(async (connection) => {
92
+ const provider = this.createProvider(connection);
93
+ // Anchor v0.31 constructor no longer takes programId
94
+ // Use the IDL's embedded metadata.address instead
95
+ const program = new anchor_1.Program(abi, provider);
96
+ const pubkey = new web3_js_1.PublicKey(args[0]);
97
+ // Cast account namespace to any to allow dynamic string
98
+ const accountNamespace = program.account;
99
+ const account = await accountNamespace[functionName].fetch(pubkey);
100
+ return account;
101
+ }, 'readContract');
108
102
  }
109
103
  /**
110
104
  * Sends a Solana transaction using a smart contract instruction.
111
105
  */
112
- writeContract(_a) {
113
- return tslib_1.__awaiter(this, arguments, void 0, function* ({ abi, signer, functionName, args = [], accounts = {}, extraSigners = [], }) {
114
- // 1. Grab or build your RPC connection however your class manages it
115
- const connection = this.connections[this.currentConnectionIndex];
116
- // 2. Create an AnchorProvider
117
- const provider = this.createProvider(connection);
118
- // 3. Instantiate the program (Anchor v0.31 will infer programId from IDL.metadata.address)
119
- const program = new anchor_1.Program(abi, provider);
120
- // 4. Deep-convert arguments into Anchor-friendly types
121
- // - BigInt -> BN
122
- // - hex strings (0x...) -> Buffer
123
- // - Uint8Array -> Buffer
124
- // - UniversalPayload object normalization (to/data/vType)
125
- const anchorify = (value) => {
126
- // Preserve BN, Buffer, PublicKey, null/undefined
127
- if (value === null ||
128
- value === undefined ||
129
- value instanceof anchor_1.BN ||
130
- Buffer.isBuffer(value) ||
131
- value instanceof web3_js_1.PublicKey)
132
- return value;
133
- // BigInt -> BN
134
- if (typeof value === 'bigint')
135
- return new anchor_1.BN(value.toString());
136
- // Hex string -> Buffer
137
- if (typeof value === 'string' && value.startsWith('0x')) {
138
- const hex = value.slice(2);
139
- if (hex.length === 0)
140
- return Buffer.alloc(0);
141
- // If odd length, left-pad a 0
142
- const normalized = hex.length % 2 === 1 ? `0${hex}` : hex;
143
- return Buffer.from(normalized, 'hex');
106
+ async writeContract({ abi, signer, functionName, args = [], accounts = {}, extraSigners = [], remainingAccounts = [], }) {
107
+ // 1. Grab or build your RPC connection however your class manages it
108
+ const connection = this.connections[this.currentConnectionIndex];
109
+ // 2. Create an AnchorProvider
110
+ const provider = this.createProvider(connection);
111
+ // 3. Instantiate the program (Anchor v0.31 will infer programId from IDL.metadata.address)
112
+ const program = new anchor_1.Program(abi, provider);
113
+ // 4. Deep-convert arguments into Anchor-friendly types
114
+ // - BigInt -> BN
115
+ // - hex strings (0x...) -> Buffer
116
+ // - Uint8Array -> Buffer
117
+ // - UniversalPayload object normalization (to/data/vType)
118
+ const anchorify = (value) => {
119
+ // Preserve BN, Buffer, PublicKey, null/undefined
120
+ if (value === null ||
121
+ value === undefined ||
122
+ value instanceof anchor_1.BN ||
123
+ Buffer.isBuffer(value) ||
124
+ value instanceof web3_js_1.PublicKey)
125
+ return value;
126
+ // BigInt -> BN
127
+ if (typeof value === 'bigint')
128
+ return new anchor_1.BN(value.toString());
129
+ // Hex string -> Buffer
130
+ if (typeof value === 'string' && value.startsWith('0x')) {
131
+ const hex = value.slice(2);
132
+ if (hex.length === 0)
133
+ return Buffer.alloc(0);
134
+ // If odd length, left-pad a 0
135
+ const normalized = hex.length % 2 === 1 ? `0${hex}` : hex;
136
+ return Buffer.from(normalized, 'hex');
137
+ }
138
+ // Uint8Array -> Buffer
139
+ if (value instanceof Uint8Array)
140
+ return Buffer.from(value);
141
+ // Array -> map recursively
142
+ if (Array.isArray(value))
143
+ return value.map((v) => anchorify(v));
144
+ // Plain object -> recurse and normalize UniversalPayload shape
145
+ if (typeof value === 'object') {
146
+ const obj = value;
147
+ const out = {};
148
+ for (const [k, v] of Object.entries(obj)) {
149
+ out[k] = anchorify(v);
144
150
  }
145
- // Uint8Array -> Buffer
146
- if (value instanceof Uint8Array)
147
- return Buffer.from(value);
148
- // Array -> map recursively
149
- if (Array.isArray(value))
150
- return value.map((v) => anchorify(v));
151
- // Plain object -> recurse and normalize UniversalPayload shape
152
- if (typeof value === 'object') {
153
- const obj = value;
154
- const out = {};
155
- for (const [k, v] of Object.entries(obj)) {
156
- out[k] = anchorify(v);
151
+ // Heuristic: normalize UniversalPayload fields expected by Anchor IDL
152
+ const hasUniversalPayloadKeys = 'to' in out &&
153
+ 'value' in out &&
154
+ 'data' in out &&
155
+ 'gasLimit' in out &&
156
+ 'maxFeePerGas' in out &&
157
+ 'maxPriorityFeePerGas' in out &&
158
+ 'nonce' in out &&
159
+ 'deadline' in out &&
160
+ 'vType' in out;
161
+ if (hasUniversalPayloadKeys) {
162
+ // to: address(20 bytes) -> Buffer(20)
163
+ if (typeof obj['to'] === 'string' && obj['to'].startsWith('0x')) {
164
+ const hex = obj['to'].slice(2).padStart(40, '0');
165
+ out['to'] = Buffer.from(hex, 'hex');
166
+ }
167
+ // data: bytes -> Buffer
168
+ if (typeof obj['data'] === 'string' && obj['data'].startsWith('0x')) {
169
+ const hex = obj['data'].slice(2);
170
+ out['data'] = hex.length
171
+ ? Buffer.from(hex, 'hex')
172
+ : Buffer.alloc(0);
157
173
  }
158
- // Heuristic: normalize UniversalPayload fields expected by Anchor IDL
159
- const hasUniversalPayloadKeys = 'to' in out &&
160
- 'value' in out &&
161
- 'data' in out &&
162
- 'gasLimit' in out &&
163
- 'maxFeePerGas' in out &&
164
- 'maxPriorityFeePerGas' in out &&
165
- 'nonce' in out &&
166
- 'deadline' in out &&
167
- 'vType' in out;
168
- if (hasUniversalPayloadKeys) {
169
- // to: address(20 bytes) -> Buffer(20)
170
- if (typeof obj['to'] === 'string' && obj['to'].startsWith('0x')) {
171
- const hex = obj['to'].slice(2).padStart(40, '0');
172
- out['to'] = Buffer.from(hex, 'hex');
173
- }
174
- // data: bytes -> Buffer
175
- if (typeof obj['data'] === 'string' && obj['data'].startsWith('0x')) {
176
- const hex = obj['data'].slice(2);
177
- out['data'] = hex.length
178
- ? Buffer.from(hex, 'hex')
179
- : Buffer.alloc(0);
180
- }
181
- // numeric fields (often provided as decimal strings from protobuf/JSON) -> BN
182
- const numericStringToBn = (val) => {
183
- if (typeof val === 'bigint')
184
- return new anchor_1.BN(val.toString());
185
- if (typeof val === 'string' && /^[0-9]+$/.test(val))
186
- return new anchor_1.BN(val);
187
- return val;
188
- };
189
- out['value'] = numericStringToBn(out['value']);
190
- out['gasLimit'] = numericStringToBn(out['gasLimit']);
191
- out['maxFeePerGas'] = numericStringToBn(out['maxFeePerGas']);
192
- out['maxPriorityFeePerGas'] = numericStringToBn(out['maxPriorityFeePerGas']);
193
- out['nonce'] = numericStringToBn(out['nonce']);
194
- out['deadline'] = numericStringToBn(out['deadline']);
195
- // vType: enum -> Anchor enum object
196
- if (typeof obj['vType'] === 'number') {
197
- out['vType'] =
198
- obj['vType'] === 0
199
- ? { signedVerification: {} }
200
- : { universalTxVerification: {} };
201
- }
202
- else if (typeof obj['vType'] === 'string') {
203
- const vt = obj['vType'].toLowerCase();
204
- if (vt.includes('signed'))
205
- out['vType'] = { signedVerification: {} };
206
- else
207
- out['vType'] = { universalTxVerification: {} };
208
- }
174
+ // numeric fields (often provided as decimal strings from protobuf/JSON) -> BN
175
+ const numericStringToBn = (val) => {
176
+ if (typeof val === 'bigint')
177
+ return new anchor_1.BN(val.toString());
178
+ if (typeof val === 'string' && /^[0-9]+$/.test(val))
179
+ return new anchor_1.BN(val);
180
+ return val;
181
+ };
182
+ out['value'] = numericStringToBn(out['value']);
183
+ out['gasLimit'] = numericStringToBn(out['gasLimit']);
184
+ out['maxFeePerGas'] = numericStringToBn(out['maxFeePerGas']);
185
+ out['maxPriorityFeePerGas'] = numericStringToBn(out['maxPriorityFeePerGas']);
186
+ out['nonce'] = numericStringToBn(out['nonce']);
187
+ out['deadline'] = numericStringToBn(out['deadline']);
188
+ // vType: enum -> Anchor enum object
189
+ if (typeof obj['vType'] === 'number') {
190
+ out['vType'] =
191
+ obj['vType'] === 0
192
+ ? { signedVerification: {} }
193
+ : { universalTxVerification: {} };
194
+ }
195
+ else if (typeof obj['vType'] === 'string') {
196
+ const vt = obj['vType'].toLowerCase();
197
+ if (vt.includes('signed'))
198
+ out['vType'] = { signedVerification: {} };
199
+ else
200
+ out['vType'] = { universalTxVerification: {} };
209
201
  }
210
- return out;
211
202
  }
212
- return value;
213
- };
214
- const convertedArgs = anchorify(args);
215
- // 5. Build the method call
216
- let builder = Array.isArray(convertedArgs) && convertedArgs.length > 0
217
- ? program.methods[functionName](...convertedArgs)
218
- : program.methods[functionName]();
219
- if (Object.keys(accounts).length > 0) {
220
- builder = builder.accounts(accounts);
203
+ return out;
221
204
  }
222
- // 6. Get the actual instruction
223
- const instruction = yield builder.instruction();
224
- // 7. Send it and return the tx signature
225
- return this.sendTransaction({
226
- instruction,
227
- signer,
228
- extraSigners,
229
- });
205
+ return value;
206
+ };
207
+ const convertedArgs = anchorify(args);
208
+ // 5. Build the method call
209
+ let builder = Array.isArray(convertedArgs) && convertedArgs.length > 0
210
+ ? program.methods[functionName](...convertedArgs)
211
+ : program.methods[functionName]();
212
+ if (Object.keys(accounts).length > 0) {
213
+ builder = builder.accounts(accounts);
214
+ }
215
+ // Positional accounts appended after the instruction's named accounts.
216
+ // Order and flags are program-defined (e.g. the PC20 burn requires
217
+ // [pc20_state readonly, pc20_mint writable]) and must be passed exactly.
218
+ if (remainingAccounts.length > 0) {
219
+ builder = builder.remainingAccounts(remainingAccounts.map((a) => ({
220
+ pubkey: a.pubkey,
221
+ isSigner: a.isSigner,
222
+ isWritable: a.isWritable,
223
+ })));
224
+ }
225
+ // 6. Get the actual instruction
226
+ const instruction = await builder.instruction();
227
+ // 7. Send it and return the tx signature
228
+ return this.sendTransaction({
229
+ instruction,
230
+ signer,
231
+ extraSigners,
230
232
  });
231
233
  }
232
234
  /**
233
235
  * Sends a set of instructions as a manually-signed Solana transaction.
234
236
  */
235
- sendTransaction(_a) {
236
- return tslib_1.__awaiter(this, arguments, void 0, function* ({ instruction, signer, extraSigners = [], }) {
237
- const connection = this.connections[this.currentConnectionIndex];
238
- const feePayer = new web3_js_1.PublicKey(signer.account.address);
239
- // Prefer an ALT-backed v0 transaction to avoid Solana's 1232-byte legacy limit
240
- const { value: alt } = yield connection.getAddressLookupTable(ALT_ADDRESS);
241
- if (!alt) {
242
- throw new Error(`Lookup table ${ALT_ADDRESS.toBase58()} not found on chain`);
243
- }
244
- const { blockhash } = yield connection.getLatestBlockhash('finalized');
245
- const messageV0 = new web3_js_1.TransactionMessage({
246
- payerKey: feePayer,
247
- recentBlockhash: blockhash,
248
- instructions: [instruction],
249
- }).compileToV0Message([alt]);
250
- const vtx = new web3_js_1.VersionedTransaction(messageV0);
251
- if (extraSigners.length > 0) {
252
- vtx.sign(extraSigners);
253
- }
254
- const txBytes = vtx.serialize();
255
- if (!signer.signAndSendTransaction) {
256
- throw new Error('signer.signTransaction is undefined');
257
- }
258
- const txHashBytes = yield signer.signAndSendTransaction(new Uint8Array(txBytes));
259
- return bs58_1.bs58.encode(Buffer.from(txHashBytes)); // Clean, readable tx hash
260
- });
237
+ async sendTransaction({ instruction, signer, extraSigners = [], }) {
238
+ const connection = this.connections[this.currentConnectionIndex];
239
+ const feePayer = new web3_js_1.PublicKey(signer.account.address);
240
+ // Prefer an ALT-backed v0 transaction to avoid Solana's 1232-byte legacy limit
241
+ const { value: alt } = await connection.getAddressLookupTable(ALT_ADDRESS);
242
+ if (!alt) {
243
+ throw new Error(`Lookup table ${ALT_ADDRESS.toBase58()} not found on chain`);
244
+ }
245
+ const { blockhash } = await connection.getLatestBlockhash('finalized');
246
+ const messageV0 = new web3_js_1.TransactionMessage({
247
+ payerKey: feePayer,
248
+ recentBlockhash: blockhash,
249
+ instructions: [instruction],
250
+ }).compileToV0Message([alt]);
251
+ const vtx = new web3_js_1.VersionedTransaction(messageV0);
252
+ if (extraSigners.length > 0) {
253
+ vtx.sign(extraSigners);
254
+ }
255
+ const txBytes = vtx.serialize();
256
+ if (!signer.signAndSendTransaction) {
257
+ throw new Error('signer.signTransaction is undefined');
258
+ }
259
+ const txHashBytes = await signer.signAndSendTransaction(new Uint8Array(txBytes));
260
+ return bs58_1.bs58.encode(Buffer.from(txHashBytes)); // Clean, readable tx hash
261
261
  }
262
262
  /**
263
263
  * Waits for a transaction to be confirmed on the blockchain.
264
264
  */
265
- confirmTransaction(signature_1) {
266
- return tslib_1.__awaiter(this, arguments, void 0, function* (signature, timeout = 30000) {
267
- const startTime = Date.now();
268
- return this.executeWithFallback((connection) => tslib_1.__awaiter(this, void 0, void 0, function* () {
269
- while (Date.now() - startTime < timeout) {
270
- const status = yield connection.getSignatureStatus(signature);
271
- if (status === null || status === void 0 ? void 0 : status.value) {
272
- if (status.value.err) {
273
- throw new Error(`Transaction failed: ${JSON.stringify(status.value.err)}`);
274
- }
275
- if (status.value.confirmationStatus === 'confirmed' ||
276
- status.value.confirmationStatus === 'finalized') {
277
- return;
278
- }
265
+ async confirmTransaction(signature, timeout = 30000) {
266
+ const startTime = Date.now();
267
+ return this.executeWithFallback(async (connection) => {
268
+ while (Date.now() - startTime < timeout) {
269
+ const status = await connection.getSignatureStatus(signature);
270
+ if (status?.value) {
271
+ if (status.value.err) {
272
+ throw new Error(`Transaction failed: ${JSON.stringify(status.value.err)}`);
273
+ }
274
+ if (status.value.confirmationStatus === 'confirmed' ||
275
+ status.value.confirmationStatus === 'finalized') {
276
+ return;
279
277
  }
280
- yield new Promise((r) => setTimeout(r, 500));
281
278
  }
282
- throw new Error(`Transaction confirmation timeout after ${timeout}ms`);
283
- }), 'confirmTransaction');
284
- });
279
+ await new Promise((r) => setTimeout(r, 500));
280
+ }
281
+ throw new Error(`Transaction confirmation timeout after ${timeout}ms`);
282
+ }, 'confirmTransaction');
285
283
  }
286
284
  /**
287
285
  * Estimates the fee (in lamports) to send a transaction with the given instructions.
288
286
  */
289
- estimateGas(_a) {
290
- return tslib_1.__awaiter(this, arguments, void 0, function* ({ instructions, signer, }) {
291
- return this.executeWithFallback((connection) => tslib_1.__awaiter(this, void 0, void 0, function* () {
292
- const feePayer = new web3_js_1.PublicKey(signer.account.address);
293
- const { blockhash, lastValidBlockHeight } = yield connection.getLatestBlockhash();
294
- const tx = new web3_js_1.Transaction({ blockhash, lastValidBlockHeight, feePayer });
295
- if (instructions.length)
296
- tx.add(...instructions);
297
- const message = tx.compileMessage();
298
- const feeResp = yield connection.getFeeForMessage(message);
299
- if (!(feeResp === null || feeResp === void 0 ? void 0 : feeResp.value))
300
- throw new Error('Failed to estimate fee');
301
- return BigInt(feeResp.value);
302
- }), 'estimateGas');
303
- });
287
+ async estimateGas({ instructions, signer, }) {
288
+ return this.executeWithFallback(async (connection) => {
289
+ const feePayer = new web3_js_1.PublicKey(signer.account.address);
290
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
291
+ const tx = new web3_js_1.Transaction({ blockhash, lastValidBlockHeight, feePayer });
292
+ if (instructions.length)
293
+ tx.add(...instructions);
294
+ const message = tx.compileMessage();
295
+ const feeResp = await connection.getFeeForMessage(message);
296
+ if (!feeResp?.value)
297
+ throw new Error('Failed to estimate fee');
298
+ return BigInt(feeResp.value);
299
+ }, 'estimateGas');
304
300
  }
305
301
  }
306
302
  exports.SvmClient = SvmClient;
@@ -40,13 +40,25 @@ export interface WriteContractParams extends ReadContractParams {
40
40
  value?: bigint;
41
41
  signer: UniversalSigner;
42
42
  /**
43
- * **For Solana only** Dynamic accounts to pass to the solana program instruction
43
+ * **For Solana only** Dynamic accounts to pass to the solana program
44
+ * instruction. `null` is valid for accounts the IDL marks `optional` —
45
+ * Anchor substitutes the program id as the on-wire "none" placeholder.
44
46
  */
45
- accounts?: Record<string, PublicKey>;
47
+ accounts?: Record<string, PublicKey | null>;
46
48
  /**
47
49
  * **For Solana only** Keypairs that should sign the transaction
48
50
  */
49
51
  extraSigners?: Keypair[];
52
+ /**
53
+ * **For Solana only** Positional accounts appended after the instruction's
54
+ * named accounts. Order and flags are program-defined — e.g. the PC20 burn
55
+ * requires exactly `[pc20_state readonly, pc20_mint writable]`.
56
+ */
57
+ remainingAccounts?: Array<{
58
+ pubkey: PublicKey;
59
+ isSigner: boolean;
60
+ isWritable: boolean;
61
+ }>;
50
62
  }
51
63
  export type TxResponse = Transaction & {
52
64
  wait: (confirmations?: number) => Promise<TransactionReceipt>;