@altiuslabs/tx-sdk 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altiuslabs/tx-sdk",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "SDK for signing and sending Altius USD multi-token transactions",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/rpc.js CHANGED
@@ -71,7 +71,7 @@ export class RpcClient {
71
71
  */
72
72
  async get_balance(address) {
73
73
  const hex = await this.request('eth_getBalance', [address, 'latest']);
74
- return BigInt(hex);
74
+ return hex && hex !== '0x' ? BigInt(hex) : 0n;
75
75
  }
76
76
 
77
77
  /**
@@ -141,7 +141,7 @@ export class RpcClient {
141
141
  // ERC20 balanceOf selector: 0x70a08231
142
142
  const data = '0x70a08231' + pad_hex(owner_address, 32).slice(2);
143
143
  const result = await this.call({ to: token_address, data });
144
- return BigInt(result);
144
+ return result && result !== '0x' ? BigInt(result) : 0n;
145
145
  }
146
146
  }
147
147
 
@@ -4,6 +4,8 @@
4
4
 
5
5
  import { keccak256, pad_hex, num_to_hex, rlp_encode } from './utils.js';
6
6
 
7
+ const RLP = require('ethereumjs-util').rlp;
8
+
7
9
  /**
8
10
  * Magic byte for fee payer signature (0x7B)
9
11
  */
@@ -182,26 +184,25 @@ export class TxBuilder {
182
184
 
183
185
  // For 0x7a transaction, encode fields WITHOUT fee_payer_signature (matches node's encode_for_signing)
184
186
  // Format: [chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, input, accessList, feeToken, feePayer, maxFeePerGasUsdAttodollars]
187
+ // IMPORTANT: Use Buffer for addresses and data to match Rust alloy-rlp encoding
185
188
  const list = [
186
- tx.chain_id,
187
- tx.nonce,
188
- tx.max_priority_fee_per_gas,
189
- tx.max_fee_per_gas,
190
- tx.gas_limit,
191
- tx.to,
192
- tx.value,
193
- tx.data,
194
- // Empty access list
195
- [],
196
- tx.fee_token,
197
- tx.fee_payer,
198
- tx.max_fee_per_gas_usd_attodollars,
189
+ BigInt(tx.chain_id),
190
+ BigInt(tx.nonce),
191
+ BigInt(tx.max_priority_fee_per_gas),
192
+ BigInt(tx.max_fee_per_gas),
193
+ BigInt(tx.gas_limit),
194
+ Buffer.from(tx.to.slice(2), 'hex'), // address as 20-byte buffer
195
+ BigInt(tx.value),
196
+ Buffer.from(tx.data.slice(2), 'hex') || Buffer.alloc(0), // data as buffer
197
+ [], // Empty access list
198
+ Buffer.from(tx.fee_token.slice(2), 'hex'), // fee_token as buffer
199
+ Buffer.from(tx.fee_payer.slice(2), 'hex'), // fee_payer as buffer
200
+ BigInt(tx.max_fee_per_gas_usd_attodollars),
199
201
  ];
200
202
 
201
203
  // Encode with type byte 0x7a prefix (matches node's encode_for_signing)
202
- const type_byte = '0x7a';
203
- const encoded = rlp_encode(list);
204
- const with_type = type_byte + encoded.slice(2);
204
+ const rlp_buf = RLP.encode(list);
205
+ const with_type = '0x7a' + rlp_buf.toString('hex');
205
206
 
206
207
  return keccak256(with_type);
207
208
  }
@@ -220,32 +221,36 @@ export class TxBuilder {
220
221
 
221
222
  const tx = this.build();
222
223
 
224
+ // Convert r, s to 32-byte buffers
225
+ const rBuffer = Buffer.from(sig.r.slice(2), 'hex');
226
+ const sBuffer = Buffer.from(sig.s.slice(2), 'hex');
227
+
223
228
  // Build signed transaction list (for EIP-2718 encoding)
224
229
  // Format matches node's rlp_encode_fields: [chainId, nonce, ..., feePayerSignature, signature]
230
+ // IMPORTANT: Use Buffer for addresses and data to match Rust alloy-rlp encoding
225
231
  const signed_fields = [
226
- tx.chain_id,
227
- tx.nonce,
228
- tx.max_priority_fee_per_gas,
229
- tx.max_fee_per_gas,
230
- tx.gas_limit,
231
- tx.to,
232
- tx.value,
233
- tx.data,
232
+ BigInt(tx.chain_id),
233
+ BigInt(tx.nonce),
234
+ BigInt(tx.max_priority_fee_per_gas),
235
+ BigInt(tx.max_fee_per_gas),
236
+ BigInt(tx.gas_limit),
237
+ Buffer.from(tx.to.slice(2), 'hex'), // address as 20-byte buffer
238
+ BigInt(tx.value),
239
+ Buffer.from(tx.data.slice(2), 'hex') || Buffer.alloc(0), // data as buffer
234
240
  [], // empty access list
235
- tx.fee_token,
236
- tx.fee_payer,
237
- tx.max_fee_per_gas_usd_attodollars,
238
- tx.fee_payer_signature,
241
+ Buffer.from(tx.fee_token.slice(2), 'hex'), // fee_token as buffer
242
+ Buffer.from(tx.fee_payer.slice(2), 'hex'), // fee_payer as buffer
243
+ BigInt(tx.max_fee_per_gas_usd_attodollars),
244
+ Buffer.from(tx.fee_payer_signature?.slice(2) || '', 'hex') || Buffer.alloc(0),
239
245
  // Signature: y_parity (1 byte), r (32 bytes), s (32 bytes)
240
246
  y_parity,
241
- sig.r,
242
- sig.s,
247
+ rBuffer,
248
+ sBuffer,
243
249
  ];
244
250
 
245
251
  // EIP-2718: first byte is type (0x7a), then RLP encoded fields
246
- const rlp_fields = rlp_encode(signed_fields);
247
- const type_byte = '0x7a';
248
- const raw_transaction = type_byte + rlp_fields.slice(2); // Remove 0x prefix from RLP output
252
+ const rlp_fields_buf = RLP.encode(signed_fields);
253
+ const raw_transaction = '0x7a' + rlp_fields_buf.toString('hex');
249
254
 
250
255
  const transaction_hash = keccak256(raw_transaction);
251
256