@rialo/ts-cdk 0.1.2 → 0.1.4

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/dist/index.mjs CHANGED
@@ -449,17 +449,36 @@ var RialoError = class _RialoError extends Error {
449
449
 
450
450
  // src/constants.ts
451
451
  var DEFAULT_NUM_ACCOUNTS = 1;
452
- var URL_MAINNET = "https://mainnet.rialo.io:4100";
453
- var URL_TESTNET = "https://testnet.rialo.io:4100";
452
+ var URL_MAINNET = "https://mainnet.rialo.io:4101";
453
+ var URL_TESTNET = "https://testnet.rialo.io:4101";
454
454
  var URL_DEVNET = "https://devnet.rialo.io:4101";
455
455
  var URL_LOCALNET = "http://localhost:4100";
456
+ var RIALO_MAINNET_CHAIN = {
457
+ id: "rialo:mainnet",
458
+ name: "Mainnet",
459
+ rpcUrl: URL_MAINNET
460
+ };
461
+ var RIALO_TESTNET_CHAIN = {
462
+ id: "rialo:testnet",
463
+ name: "Testnet",
464
+ rpcUrl: URL_TESTNET
465
+ };
466
+ var RIALO_DEVNET_CHAIN = {
467
+ id: "rialo:devnet",
468
+ name: "Devnet",
469
+ rpcUrl: URL_DEVNET
470
+ };
471
+ var RIALO_LOCALNET_CHAIN = {
472
+ id: "rialo:localnet",
473
+ name: "Localhost",
474
+ rpcUrl: URL_LOCALNET
475
+ };
456
476
  var SYSTEM_PROGRAM_ID = "11111111111111111111111111111111";
457
477
  var BASE_DERIVATION_PATH = "m/44'/756'/";
458
478
  var KELVIN_PER_RLO = 1e9;
459
479
  var PUBLIC_KEY_LENGTH = 32;
460
480
  var SECRET_KEY_LENGTH = 32;
461
481
  var SIGNATURE_LENGTH = 64;
462
- var BLOCKHASH_LENGTH = 32;
463
482
 
464
483
  // src/transaction/account-meta-table.ts
465
484
  var AccountMetaTable = class {
@@ -1221,395 +1240,43 @@ function encodeBorshData(_schema) {
1221
1240
  throw new Error("Use class-based Borsh serialization with decorators");
1222
1241
  }
1223
1242
 
1224
- // node_modules/@scure/base/index.js
1225
- function isBytes(a) {
1226
- return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
1227
- }
1228
- function isArrayOf(isString, arr) {
1229
- if (!Array.isArray(arr))
1230
- return false;
1231
- if (arr.length === 0)
1232
- return true;
1233
- if (isString) {
1234
- return arr.every((item) => typeof item === "string");
1235
- } else {
1236
- return arr.every((item) => Number.isSafeInteger(item));
1243
+ // src/crypto/errors.ts
1244
+ var CryptoErrorCode = /* @__PURE__ */ ((CryptoErrorCode2) => {
1245
+ CryptoErrorCode2["INVALID_KEY_LENGTH"] = "INVALID_KEY_LENGTH";
1246
+ CryptoErrorCode2["INVALID_SIGNATURE"] = "INVALID_SIGNATURE";
1247
+ CryptoErrorCode2["INVALID_PUBLIC_KEY"] = "INVALID_PUBLIC_KEY";
1248
+ CryptoErrorCode2["INVALID_BLOCKHASH"] = "INVALID_BLOCKHASH";
1249
+ CryptoErrorCode2["INVALID_MNEMONIC"] = "INVALID_MNEMONIC";
1250
+ CryptoErrorCode2["KEY_DERIVATION_FAILED"] = "KEY_DERIVATION_FAILED";
1251
+ CryptoErrorCode2["KEYPAIR_DISPOSED"] = "KEYPAIR_DISPOSED";
1252
+ return CryptoErrorCode2;
1253
+ })(CryptoErrorCode || {});
1254
+ var CryptoError = class _CryptoError extends Error {
1255
+ code;
1256
+ details;
1257
+ constructor(code, message, details) {
1258
+ super(message);
1259
+ this.name = "CryptoError";
1260
+ this.code = code;
1261
+ this.details = details;
1237
1262
  }
1238
- }
1239
- function afn(input) {
1240
- if (typeof input !== "function")
1241
- throw new Error("function expected");
1242
- return true;
1243
- }
1244
- function astr(label, input) {
1245
- if (typeof input !== "string")
1246
- throw new Error(`${label}: string expected`);
1247
- return true;
1248
- }
1249
- function anumber(n) {
1250
- if (!Number.isSafeInteger(n))
1251
- throw new Error(`invalid integer: ${n}`);
1252
- }
1253
- function aArr(input) {
1254
- if (!Array.isArray(input))
1255
- throw new Error("array expected");
1256
- }
1257
- function astrArr(label, input) {
1258
- if (!isArrayOf(true, input))
1259
- throw new Error(`${label}: array of strings expected`);
1260
- }
1261
- function anumArr(label, input) {
1262
- if (!isArrayOf(false, input))
1263
- throw new Error(`${label}: array of numbers expected`);
1264
- }
1265
- // @__NO_SIDE_EFFECTS__
1266
- function chain(...args) {
1267
- const id = (a) => a;
1268
- const wrap = (a, b) => (c) => a(b(c));
1269
- const encode = args.map((x) => x.encode).reduceRight(wrap, id);
1270
- const decode = args.map((x) => x.decode).reduce(wrap, id);
1271
- return { encode, decode };
1272
- }
1273
- // @__NO_SIDE_EFFECTS__
1274
- function alphabet(letters) {
1275
- const lettersA = typeof letters === "string" ? letters.split("") : letters;
1276
- const len = lettersA.length;
1277
- astrArr("alphabet", lettersA);
1278
- const indexes = new Map(lettersA.map((l, i) => [l, i]));
1279
- return {
1280
- encode: (digits) => {
1281
- aArr(digits);
1282
- return digits.map((i) => {
1283
- if (!Number.isSafeInteger(i) || i < 0 || i >= len)
1284
- throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
1285
- return lettersA[i];
1286
- });
1287
- },
1288
- decode: (input) => {
1289
- aArr(input);
1290
- return input.map((letter) => {
1291
- astr("alphabet.decode", letter);
1292
- const i = indexes.get(letter);
1293
- if (i === void 0)
1294
- throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
1295
- return i;
1296
- });
1297
- }
1298
- };
1299
- }
1300
- // @__NO_SIDE_EFFECTS__
1301
- function join(separator = "") {
1302
- astr("join", separator);
1303
- return {
1304
- encode: (from) => {
1305
- astrArr("join.decode", from);
1306
- return from.join(separator);
1307
- },
1308
- decode: (to) => {
1309
- astr("join.decode", to);
1310
- return to.split(separator);
1311
- }
1312
- };
1313
- }
1314
- // @__NO_SIDE_EFFECTS__
1315
- function padding(bits, chr = "=") {
1316
- anumber(bits);
1317
- astr("padding", chr);
1318
- return {
1319
- encode(data) {
1320
- astrArr("padding.encode", data);
1321
- while (data.length * bits % 8)
1322
- data.push(chr);
1323
- return data;
1324
- },
1325
- decode(input) {
1326
- astrArr("padding.decode", input);
1327
- let end = input.length;
1328
- if (end * bits % 8)
1329
- throw new Error("padding: invalid, string should have whole number of bytes");
1330
- for (; end > 0 && input[end - 1] === chr; end--) {
1331
- const last = end - 1;
1332
- const byte = last * bits;
1333
- if (byte % 8 === 0)
1334
- throw new Error("padding: invalid, string has too much padding");
1335
- }
1336
- return input.slice(0, end);
1337
- }
1338
- };
1339
- }
1340
- function convertRadix(data, from, to) {
1341
- if (from < 2)
1342
- throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
1343
- if (to < 2)
1344
- throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
1345
- aArr(data);
1346
- if (!data.length)
1347
- return [];
1348
- let pos = 0;
1349
- const res = [];
1350
- const digits = Array.from(data, (d) => {
1351
- anumber(d);
1352
- if (d < 0 || d >= from)
1353
- throw new Error(`invalid integer: ${d}`);
1354
- return d;
1355
- });
1356
- const dlen = digits.length;
1357
- while (true) {
1358
- let carry = 0;
1359
- let done = true;
1360
- for (let i = pos; i < dlen; i++) {
1361
- const digit = digits[i];
1362
- const fromCarry = from * carry;
1363
- const digitBase = fromCarry + digit;
1364
- if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
1365
- throw new Error("convertRadix: carry overflow");
1366
- }
1367
- const div = digitBase / to;
1368
- carry = digitBase % to;
1369
- const rounded = Math.floor(div);
1370
- digits[i] = rounded;
1371
- if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
1372
- throw new Error("convertRadix: carry overflow");
1373
- if (!done)
1374
- continue;
1375
- else if (!rounded)
1376
- pos = i;
1377
- else
1378
- done = false;
1379
- }
1380
- res.push(carry);
1381
- if (done)
1382
- break;
1263
+ static invalidKeyLength(expected, actual) {
1264
+ return new _CryptoError(
1265
+ "INVALID_KEY_LENGTH" /* INVALID_KEY_LENGTH */,
1266
+ `Invalid key length: expected ${expected} bytes, got ${actual} bytes`,
1267
+ { expected, actual }
1268
+ );
1383
1269
  }
1384
- for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
1385
- res.push(0);
1386
- return res.reverse();
1387
- }
1388
- var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
1389
- var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
1390
- var powers = /* @__PURE__ */ (() => {
1391
- let res = [];
1392
- for (let i = 0; i < 40; i++)
1393
- res.push(2 ** i);
1394
- return res;
1395
- })();
1396
- function convertRadix2(data, from, to, padding2) {
1397
- aArr(data);
1398
- if (from <= 0 || from > 32)
1399
- throw new Error(`convertRadix2: wrong from=${from}`);
1400
- if (to <= 0 || to > 32)
1401
- throw new Error(`convertRadix2: wrong to=${to}`);
1402
- if (/* @__PURE__ */ radix2carry(from, to) > 32) {
1403
- throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
1270
+ static invalidMnemonic(reason) {
1271
+ const message = reason ? `Invalid mnemonic: ${reason}` : "Invalid mnemonic phrase. Check that all words are valid and in the correct order.";
1272
+ return new _CryptoError("INVALID_MNEMONIC" /* INVALID_MNEMONIC */, message);
1404
1273
  }
1405
- let carry = 0;
1406
- let pos = 0;
1407
- const max = powers[from];
1408
- const mask = powers[to] - 1;
1409
- const res = [];
1410
- for (const n of data) {
1411
- anumber(n);
1412
- if (n >= max)
1413
- throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
1414
- carry = carry << from | n;
1415
- if (pos + from > 32)
1416
- throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
1417
- pos += from;
1418
- for (; pos >= to; pos -= to)
1419
- res.push((carry >> pos - to & mask) >>> 0);
1420
- const pow = powers[pos];
1421
- if (pow === void 0)
1422
- throw new Error("invalid carry");
1423
- carry &= pow - 1;
1424
- }
1425
- carry = carry << to - pos & mask;
1426
- if (!padding2 && pos >= from)
1427
- throw new Error("Excess padding");
1428
- if (!padding2 && carry > 0)
1429
- throw new Error(`Non-zero padding: ${carry}`);
1430
- if (padding2 && pos > 0)
1431
- res.push(carry >>> 0);
1432
- return res;
1433
- }
1434
- // @__NO_SIDE_EFFECTS__
1435
- function radix(num) {
1436
- anumber(num);
1437
- const _256 = 2 ** 8;
1438
- return {
1439
- encode: (bytes) => {
1440
- if (!isBytes(bytes))
1441
- throw new Error("radix.encode input should be Uint8Array");
1442
- return convertRadix(Array.from(bytes), _256, num);
1443
- },
1444
- decode: (digits) => {
1445
- anumArr("radix.decode", digits);
1446
- return Uint8Array.from(convertRadix(digits, num, _256));
1447
- }
1448
- };
1449
- }
1450
- // @__NO_SIDE_EFFECTS__
1451
- function radix2(bits, revPadding = false) {
1452
- anumber(bits);
1453
- if (bits <= 0 || bits > 32)
1454
- throw new Error("radix2: bits should be in (0..32]");
1455
- if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
1456
- throw new Error("radix2: carry overflow");
1457
- return {
1458
- encode: (bytes) => {
1459
- if (!isBytes(bytes))
1460
- throw new Error("radix2.encode input should be Uint8Array");
1461
- return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
1462
- },
1463
- decode: (digits) => {
1464
- anumArr("radix2.decode", digits);
1465
- return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
1466
- }
1467
- };
1468
- }
1469
- function checksum(len, fn) {
1470
- anumber(len);
1471
- afn(fn);
1472
- return {
1473
- encode(data) {
1474
- if (!isBytes(data))
1475
- throw new Error("checksum.encode: input should be Uint8Array");
1476
- const sum = fn(data).slice(0, len);
1477
- const res = new Uint8Array(data.length + len);
1478
- res.set(data);
1479
- res.set(sum, data.length);
1480
- return res;
1481
- },
1482
- decode(data) {
1483
- if (!isBytes(data))
1484
- throw new Error("checksum.decode: input should be Uint8Array");
1485
- const payload = data.slice(0, -len);
1486
- const oldChecksum = data.slice(-len);
1487
- const newChecksum = fn(payload).slice(0, len);
1488
- for (let i = 0; i < len; i++)
1489
- if (newChecksum[i] !== oldChecksum[i])
1490
- throw new Error("Invalid checksum");
1491
- return payload;
1492
- }
1493
- };
1494
- }
1495
- var utils = {
1496
- alphabet,
1497
- chain,
1498
- checksum,
1499
- convertRadix,
1500
- convertRadix2,
1501
- radix,
1502
- radix2,
1503
- join,
1504
- padding
1505
- };
1506
- var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
1507
- var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
1508
-
1509
- // src/crypto/blockhash.ts
1510
- var Blockhash = class _Blockhash {
1511
- bytes;
1512
- constructor(bytes) {
1513
- if (bytes.length !== BLOCKHASH_LENGTH) {
1514
- throw CryptoError.invalidKeyLength(BLOCKHASH_LENGTH, bytes.length);
1515
- }
1516
- this.bytes = new Uint8Array(bytes);
1517
- }
1518
- /**
1519
- * Creates a Blockhash from raw bytes.
1520
- *
1521
- * @param bytes - 32-byte blockhash
1522
- * @throws {CryptoError} If bytes length is not 32
1523
- */
1524
- static fromBytes(bytes) {
1525
- return new _Blockhash(bytes);
1526
- }
1527
- /**
1528
- * Creates a Blockhash from a base58-encoded string.
1529
- *
1530
- * @param str - Base58-encoded blockhash
1531
- * @throws {CryptoError} If string is invalid or decodes to wrong length
1532
- */
1533
- static fromString(str) {
1534
- try {
1535
- const bytes = base58.decode(str);
1536
- return new _Blockhash(bytes);
1537
- } catch (error) {
1538
- throw new CryptoError(
1539
- "INVALID_BLOCKHASH" /* INVALID_BLOCKHASH */,
1540
- `Invalid base58 blockhash: ${error instanceof Error ? error.message : "unknown error"}`,
1541
- { input: str }
1542
- );
1543
- }
1544
- }
1545
- /**
1546
- * Returns a copy of the raw bytes.
1547
- */
1548
- toBytes() {
1549
- return new Uint8Array(this.bytes);
1550
- }
1551
- /**
1552
- * Returns the base58-encoded string representation.
1553
- */
1554
- toString() {
1555
- return base58.encode(this.bytes);
1556
- }
1557
- /**
1558
- * Checks equality with another blockhash using constant-time comparison.
1559
- */
1560
- equals(other) {
1561
- if (!other) return false;
1562
- if (this.bytes.length !== other.bytes.length) return false;
1563
- for (let i = 0; i < this.bytes.length; i++) {
1564
- if (this.bytes[i] !== other.bytes[i]) return false;
1565
- }
1566
- return true;
1567
- }
1568
- /**
1569
- * JSON serialization (returns base58 string).
1570
- */
1571
- toJSON() {
1572
- return this.toString();
1573
- }
1574
- };
1575
-
1576
- // src/crypto/errors.ts
1577
- var CryptoErrorCode = /* @__PURE__ */ ((CryptoErrorCode2) => {
1578
- CryptoErrorCode2["INVALID_KEY_LENGTH"] = "INVALID_KEY_LENGTH";
1579
- CryptoErrorCode2["INVALID_SIGNATURE"] = "INVALID_SIGNATURE";
1580
- CryptoErrorCode2["INVALID_PUBLIC_KEY"] = "INVALID_PUBLIC_KEY";
1581
- CryptoErrorCode2["INVALID_BLOCKHASH"] = "INVALID_BLOCKHASH";
1582
- CryptoErrorCode2["INVALID_MNEMONIC"] = "INVALID_MNEMONIC";
1583
- CryptoErrorCode2["KEY_DERIVATION_FAILED"] = "KEY_DERIVATION_FAILED";
1584
- CryptoErrorCode2["KEYPAIR_DISPOSED"] = "KEYPAIR_DISPOSED";
1585
- return CryptoErrorCode2;
1586
- })(CryptoErrorCode || {});
1587
- var CryptoError = class _CryptoError extends Error {
1588
- code;
1589
- details;
1590
- constructor(code, message, details) {
1591
- super(message);
1592
- this.name = "CryptoError";
1593
- this.code = code;
1594
- this.details = details;
1595
- }
1596
- static invalidKeyLength(expected, actual) {
1597
- return new _CryptoError(
1598
- "INVALID_KEY_LENGTH" /* INVALID_KEY_LENGTH */,
1599
- `Invalid key length: expected ${expected} bytes, got ${actual} bytes`,
1600
- { expected, actual }
1601
- );
1602
- }
1603
- static invalidMnemonic(reason) {
1604
- const message = reason ? `Invalid mnemonic: ${reason}` : "Invalid mnemonic phrase. Check that all words are valid and in the correct order.";
1605
- return new _CryptoError("INVALID_MNEMONIC" /* INVALID_MNEMONIC */, message);
1606
- }
1607
- static keyDerivationFailed(path, cause) {
1608
- return new _CryptoError(
1609
- "KEY_DERIVATION_FAILED" /* KEY_DERIVATION_FAILED */,
1610
- `Failed to derive key at path: ${path}`,
1611
- { path, cause: cause?.message }
1612
- );
1274
+ static keyDerivationFailed(path, cause) {
1275
+ return new _CryptoError(
1276
+ "KEY_DERIVATION_FAILED" /* KEY_DERIVATION_FAILED */,
1277
+ `Failed to derive key at path: ${path}`,
1278
+ { path, cause: cause?.message }
1279
+ );
1613
1280
  }
1614
1281
  static keypairDisposed() {
1615
1282
  return new _CryptoError(
@@ -1644,9 +1311,9 @@ var err = (message = "") => {
1644
1311
  };
1645
1312
  var isBig = (n) => typeof n === "bigint";
1646
1313
  var isStr = (s) => typeof s === "string";
1647
- var isBytes2 = (a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
1314
+ var isBytes = (a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
1648
1315
  var abytes = (value, length, title = "") => {
1649
- const bytes = isBytes2(value);
1316
+ const bytes = isBytes(value);
1650
1317
  const len = value?.length;
1651
1318
  const needsLen = length !== void 0;
1652
1319
  if (!bytes || needsLen && len !== length) {
@@ -2100,17 +1767,17 @@ var wNAF = (n) => {
2100
1767
  };
2101
1768
 
2102
1769
  // node_modules/@noble/hashes/utils.js
2103
- function isBytes3(a) {
1770
+ function isBytes2(a) {
2104
1771
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
2105
1772
  }
2106
- function anumber2(n, title = "") {
1773
+ function anumber(n, title = "") {
2107
1774
  if (!Number.isSafeInteger(n) || n < 0) {
2108
1775
  const prefix = title && `"${title}" `;
2109
1776
  throw new Error(`${prefix}expected integer >0, got ${n}`);
2110
1777
  }
2111
1778
  }
2112
1779
  function abytes2(value, length, title = "") {
2113
- const bytes = isBytes3(value);
1780
+ const bytes = isBytes2(value);
2114
1781
  const len = value?.length;
2115
1782
  const needsLen = length !== void 0;
2116
1783
  if (!bytes || needsLen && len !== length) {
@@ -2124,8 +1791,8 @@ function abytes2(value, length, title = "") {
2124
1791
  function ahash(h2) {
2125
1792
  if (typeof h2 !== "function" || typeof h2.create !== "function")
2126
1793
  throw new Error("Hash must wrapped by utils.createHasher");
2127
- anumber2(h2.outputLen);
2128
- anumber2(h2.blockLen);
1794
+ anumber(h2.outputLen);
1795
+ anumber(h2.blockLen);
2129
1796
  }
2130
1797
  function aexists(instance, checkFinished = true) {
2131
1798
  if (instance.destroyed)
@@ -2525,106 +2192,391 @@ var sha512 = /* @__PURE__ */ createHasher(
2525
2192
  /* @__PURE__ */ oidNist(3)
2526
2193
  );
2527
2194
 
2528
- // src/crypto/public-key.ts
2529
- var PublicKey = class _PublicKey {
2530
- bytes;
2531
- constructor(bytes) {
2532
- if (bytes.length !== PUBLIC_KEY_LENGTH) {
2533
- throw CryptoError.invalidKeyLength(PUBLIC_KEY_LENGTH, bytes.length);
2534
- }
2535
- this.bytes = new Uint8Array(bytes);
2536
- }
2537
- /**
2538
- * Creates a PublicKey from raw bytes.
2539
- *
2540
- * @param bytes - 32-byte Ed25519 public key
2541
- * @throws {CryptoError} If bytes length is not 32
2542
- */
2543
- static fromBytes(bytes) {
2544
- return new _PublicKey(bytes);
2545
- }
2546
- /**
2547
- * Creates a PublicKey from a base58-encoded string.
2548
- *
2549
- * @param str - Base58-encoded public key
2550
- * @throws {CryptoError} If string is invalid or decodes to wrong length
2551
- */
2552
- static fromString(str) {
2553
- try {
2554
- const bytes = base58.decode(str);
2555
- return new _PublicKey(bytes);
2556
- } catch (error) {
2557
- throw new CryptoError(
2558
- "INVALID_PUBLIC_KEY" /* INVALID_PUBLIC_KEY */,
2559
- `Invalid base58 public key: ${error instanceof Error ? error.message : "unknown error"}`,
2560
- { input: str }
2561
- );
2562
- }
2563
- }
2564
- /**
2565
- * Returns a copy of the raw bytes.
2566
- */
2567
- toBytes() {
2568
- return new Uint8Array(this.bytes);
2569
- }
2570
- /**
2571
- * Returns the base58-encoded string representation.
2572
- */
2573
- toString() {
2574
- return base58.encode(this.bytes);
2575
- }
2576
- /**
2577
- * Checks equality with another public key using constant-time comparison.
2578
- */
2579
- equals(other) {
2580
- if (!other) return false;
2581
- if (this.bytes.length !== other.bytes.length) return false;
2582
- for (let i = 0; i < this.bytes.length; i++) {
2583
- if (this.bytes[i] !== other.bytes[i]) return false;
2584
- }
2195
+ // node_modules/@scure/base/index.js
2196
+ function isBytes3(a) {
2197
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
2198
+ }
2199
+ function isArrayOf(isString, arr) {
2200
+ if (!Array.isArray(arr))
2201
+ return false;
2202
+ if (arr.length === 0)
2585
2203
  return true;
2204
+ if (isString) {
2205
+ return arr.every((item) => typeof item === "string");
2206
+ } else {
2207
+ return arr.every((item) => Number.isSafeInteger(item));
2586
2208
  }
2587
- /**
2588
- * Verifies an Ed25519 signature over a message.
2589
- *
2590
- * @param message - Message bytes that were signed
2591
- * @param signature - Signature to verify
2592
- * @returns True if signature is valid, false otherwise
2593
- *
2594
- * @example
2595
- * ```typescript
2596
- * const message = new Uint8Array([1, 2, 3]);
2597
- * const signature = keypair.sign(message);
2598
- * const isValid = keypair.publicKey.verify(message, signature);
2599
- * ```
2600
- */
2601
- verify(message, signature) {
2602
- return verify(
2603
- signature.toBytes(),
2604
- message,
2605
- this.bytes
2606
- );
2607
- }
2608
- /**
2609
- * JSON serialization (returns base58 string).
2610
- */
2611
- toJSON() {
2612
- return this.toString();
2613
- }
2614
- };
2615
-
2616
- // src/crypto/signature.ts
2617
- var Signature = class _Signature {
2618
- bytes;
2619
- constructor(bytes) {
2620
- if (bytes.length !== SIGNATURE_LENGTH) {
2621
- throw CryptoError.invalidKeyLength(SIGNATURE_LENGTH, bytes.length);
2622
- }
2623
- this.bytes = new Uint8Array(bytes);
2624
- }
2625
- /**
2626
- * Creates a Signature from raw bytes.
2627
- *
2209
+ }
2210
+ function afn(input) {
2211
+ if (typeof input !== "function")
2212
+ throw new Error("function expected");
2213
+ return true;
2214
+ }
2215
+ function astr(label, input) {
2216
+ if (typeof input !== "string")
2217
+ throw new Error(`${label}: string expected`);
2218
+ return true;
2219
+ }
2220
+ function anumber2(n) {
2221
+ if (!Number.isSafeInteger(n))
2222
+ throw new Error(`invalid integer: ${n}`);
2223
+ }
2224
+ function aArr(input) {
2225
+ if (!Array.isArray(input))
2226
+ throw new Error("array expected");
2227
+ }
2228
+ function astrArr(label, input) {
2229
+ if (!isArrayOf(true, input))
2230
+ throw new Error(`${label}: array of strings expected`);
2231
+ }
2232
+ function anumArr(label, input) {
2233
+ if (!isArrayOf(false, input))
2234
+ throw new Error(`${label}: array of numbers expected`);
2235
+ }
2236
+ // @__NO_SIDE_EFFECTS__
2237
+ function chain(...args) {
2238
+ const id = (a) => a;
2239
+ const wrap = (a, b) => (c) => a(b(c));
2240
+ const encode = args.map((x) => x.encode).reduceRight(wrap, id);
2241
+ const decode = args.map((x) => x.decode).reduce(wrap, id);
2242
+ return { encode, decode };
2243
+ }
2244
+ // @__NO_SIDE_EFFECTS__
2245
+ function alphabet(letters) {
2246
+ const lettersA = typeof letters === "string" ? letters.split("") : letters;
2247
+ const len = lettersA.length;
2248
+ astrArr("alphabet", lettersA);
2249
+ const indexes = new Map(lettersA.map((l, i) => [l, i]));
2250
+ return {
2251
+ encode: (digits) => {
2252
+ aArr(digits);
2253
+ return digits.map((i) => {
2254
+ if (!Number.isSafeInteger(i) || i < 0 || i >= len)
2255
+ throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
2256
+ return lettersA[i];
2257
+ });
2258
+ },
2259
+ decode: (input) => {
2260
+ aArr(input);
2261
+ return input.map((letter) => {
2262
+ astr("alphabet.decode", letter);
2263
+ const i = indexes.get(letter);
2264
+ if (i === void 0)
2265
+ throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
2266
+ return i;
2267
+ });
2268
+ }
2269
+ };
2270
+ }
2271
+ // @__NO_SIDE_EFFECTS__
2272
+ function join(separator = "") {
2273
+ astr("join", separator);
2274
+ return {
2275
+ encode: (from) => {
2276
+ astrArr("join.decode", from);
2277
+ return from.join(separator);
2278
+ },
2279
+ decode: (to) => {
2280
+ astr("join.decode", to);
2281
+ return to.split(separator);
2282
+ }
2283
+ };
2284
+ }
2285
+ // @__NO_SIDE_EFFECTS__
2286
+ function padding(bits, chr = "=") {
2287
+ anumber2(bits);
2288
+ astr("padding", chr);
2289
+ return {
2290
+ encode(data) {
2291
+ astrArr("padding.encode", data);
2292
+ while (data.length * bits % 8)
2293
+ data.push(chr);
2294
+ return data;
2295
+ },
2296
+ decode(input) {
2297
+ astrArr("padding.decode", input);
2298
+ let end = input.length;
2299
+ if (end * bits % 8)
2300
+ throw new Error("padding: invalid, string should have whole number of bytes");
2301
+ for (; end > 0 && input[end - 1] === chr; end--) {
2302
+ const last = end - 1;
2303
+ const byte = last * bits;
2304
+ if (byte % 8 === 0)
2305
+ throw new Error("padding: invalid, string has too much padding");
2306
+ }
2307
+ return input.slice(0, end);
2308
+ }
2309
+ };
2310
+ }
2311
+ function convertRadix(data, from, to) {
2312
+ if (from < 2)
2313
+ throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
2314
+ if (to < 2)
2315
+ throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
2316
+ aArr(data);
2317
+ if (!data.length)
2318
+ return [];
2319
+ let pos = 0;
2320
+ const res = [];
2321
+ const digits = Array.from(data, (d) => {
2322
+ anumber2(d);
2323
+ if (d < 0 || d >= from)
2324
+ throw new Error(`invalid integer: ${d}`);
2325
+ return d;
2326
+ });
2327
+ const dlen = digits.length;
2328
+ while (true) {
2329
+ let carry = 0;
2330
+ let done = true;
2331
+ for (let i = pos; i < dlen; i++) {
2332
+ const digit = digits[i];
2333
+ const fromCarry = from * carry;
2334
+ const digitBase = fromCarry + digit;
2335
+ if (!Number.isSafeInteger(digitBase) || fromCarry / from !== carry || digitBase - digit !== fromCarry) {
2336
+ throw new Error("convertRadix: carry overflow");
2337
+ }
2338
+ const div = digitBase / to;
2339
+ carry = digitBase % to;
2340
+ const rounded = Math.floor(div);
2341
+ digits[i] = rounded;
2342
+ if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
2343
+ throw new Error("convertRadix: carry overflow");
2344
+ if (!done)
2345
+ continue;
2346
+ else if (!rounded)
2347
+ pos = i;
2348
+ else
2349
+ done = false;
2350
+ }
2351
+ res.push(carry);
2352
+ if (done)
2353
+ break;
2354
+ }
2355
+ for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
2356
+ res.push(0);
2357
+ return res.reverse();
2358
+ }
2359
+ var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
2360
+ var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
2361
+ var powers = /* @__PURE__ */ (() => {
2362
+ let res = [];
2363
+ for (let i = 0; i < 40; i++)
2364
+ res.push(2 ** i);
2365
+ return res;
2366
+ })();
2367
+ function convertRadix2(data, from, to, padding2) {
2368
+ aArr(data);
2369
+ if (from <= 0 || from > 32)
2370
+ throw new Error(`convertRadix2: wrong from=${from}`);
2371
+ if (to <= 0 || to > 32)
2372
+ throw new Error(`convertRadix2: wrong to=${to}`);
2373
+ if (/* @__PURE__ */ radix2carry(from, to) > 32) {
2374
+ throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
2375
+ }
2376
+ let carry = 0;
2377
+ let pos = 0;
2378
+ const max = powers[from];
2379
+ const mask = powers[to] - 1;
2380
+ const res = [];
2381
+ for (const n of data) {
2382
+ anumber2(n);
2383
+ if (n >= max)
2384
+ throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
2385
+ carry = carry << from | n;
2386
+ if (pos + from > 32)
2387
+ throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
2388
+ pos += from;
2389
+ for (; pos >= to; pos -= to)
2390
+ res.push((carry >> pos - to & mask) >>> 0);
2391
+ const pow = powers[pos];
2392
+ if (pow === void 0)
2393
+ throw new Error("invalid carry");
2394
+ carry &= pow - 1;
2395
+ }
2396
+ carry = carry << to - pos & mask;
2397
+ if (!padding2 && pos >= from)
2398
+ throw new Error("Excess padding");
2399
+ if (!padding2 && carry > 0)
2400
+ throw new Error(`Non-zero padding: ${carry}`);
2401
+ if (padding2 && pos > 0)
2402
+ res.push(carry >>> 0);
2403
+ return res;
2404
+ }
2405
+ // @__NO_SIDE_EFFECTS__
2406
+ function radix(num) {
2407
+ anumber2(num);
2408
+ const _256 = 2 ** 8;
2409
+ return {
2410
+ encode: (bytes) => {
2411
+ if (!isBytes3(bytes))
2412
+ throw new Error("radix.encode input should be Uint8Array");
2413
+ return convertRadix(Array.from(bytes), _256, num);
2414
+ },
2415
+ decode: (digits) => {
2416
+ anumArr("radix.decode", digits);
2417
+ return Uint8Array.from(convertRadix(digits, num, _256));
2418
+ }
2419
+ };
2420
+ }
2421
+ // @__NO_SIDE_EFFECTS__
2422
+ function radix2(bits, revPadding = false) {
2423
+ anumber2(bits);
2424
+ if (bits <= 0 || bits > 32)
2425
+ throw new Error("radix2: bits should be in (0..32]");
2426
+ if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
2427
+ throw new Error("radix2: carry overflow");
2428
+ return {
2429
+ encode: (bytes) => {
2430
+ if (!isBytes3(bytes))
2431
+ throw new Error("radix2.encode input should be Uint8Array");
2432
+ return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
2433
+ },
2434
+ decode: (digits) => {
2435
+ anumArr("radix2.decode", digits);
2436
+ return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
2437
+ }
2438
+ };
2439
+ }
2440
+ function checksum(len, fn) {
2441
+ anumber2(len);
2442
+ afn(fn);
2443
+ return {
2444
+ encode(data) {
2445
+ if (!isBytes3(data))
2446
+ throw new Error("checksum.encode: input should be Uint8Array");
2447
+ const sum = fn(data).slice(0, len);
2448
+ const res = new Uint8Array(data.length + len);
2449
+ res.set(data);
2450
+ res.set(sum, data.length);
2451
+ return res;
2452
+ },
2453
+ decode(data) {
2454
+ if (!isBytes3(data))
2455
+ throw new Error("checksum.decode: input should be Uint8Array");
2456
+ const payload = data.slice(0, -len);
2457
+ const oldChecksum = data.slice(-len);
2458
+ const newChecksum = fn(payload).slice(0, len);
2459
+ for (let i = 0; i < len; i++)
2460
+ if (newChecksum[i] !== oldChecksum[i])
2461
+ throw new Error("Invalid checksum");
2462
+ return payload;
2463
+ }
2464
+ };
2465
+ }
2466
+ var utils = {
2467
+ alphabet,
2468
+ chain,
2469
+ checksum,
2470
+ convertRadix,
2471
+ convertRadix2,
2472
+ radix,
2473
+ radix2,
2474
+ join,
2475
+ padding
2476
+ };
2477
+ var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
2478
+ var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
2479
+
2480
+ // src/crypto/public-key.ts
2481
+ var PublicKey = class _PublicKey {
2482
+ bytes;
2483
+ constructor(bytes) {
2484
+ if (bytes.length !== PUBLIC_KEY_LENGTH) {
2485
+ throw CryptoError.invalidKeyLength(PUBLIC_KEY_LENGTH, bytes.length);
2486
+ }
2487
+ this.bytes = new Uint8Array(bytes);
2488
+ }
2489
+ /**
2490
+ * Creates a PublicKey from raw bytes.
2491
+ *
2492
+ * @param bytes - 32-byte Ed25519 public key
2493
+ * @throws {CryptoError} If bytes length is not 32
2494
+ */
2495
+ static fromBytes(bytes) {
2496
+ return new _PublicKey(bytes);
2497
+ }
2498
+ /**
2499
+ * Creates a PublicKey from a base58-encoded string.
2500
+ *
2501
+ * @param str - Base58-encoded public key
2502
+ * @throws {CryptoError} If string is invalid or decodes to wrong length
2503
+ */
2504
+ static fromString(str) {
2505
+ try {
2506
+ const bytes = base58.decode(str);
2507
+ return new _PublicKey(bytes);
2508
+ } catch (error) {
2509
+ throw new CryptoError(
2510
+ "INVALID_PUBLIC_KEY" /* INVALID_PUBLIC_KEY */,
2511
+ `Invalid base58 public key: ${error instanceof Error ? error.message : "unknown error"}`,
2512
+ { input: str }
2513
+ );
2514
+ }
2515
+ }
2516
+ /**
2517
+ * Returns a copy of the raw bytes.
2518
+ */
2519
+ toBytes() {
2520
+ return new Uint8Array(this.bytes);
2521
+ }
2522
+ /**
2523
+ * Returns the base58-encoded string representation.
2524
+ */
2525
+ toString() {
2526
+ return base58.encode(this.bytes);
2527
+ }
2528
+ /**
2529
+ * Checks equality with another public key using constant-time comparison.
2530
+ */
2531
+ equals(other) {
2532
+ if (!other) return false;
2533
+ if (this.bytes.length !== other.bytes.length) return false;
2534
+ for (let i = 0; i < this.bytes.length; i++) {
2535
+ if (this.bytes[i] !== other.bytes[i]) return false;
2536
+ }
2537
+ return true;
2538
+ }
2539
+ /**
2540
+ * Verifies an Ed25519 signature over a message.
2541
+ *
2542
+ * @param message - Message bytes that were signed
2543
+ * @param signature - Signature to verify
2544
+ * @returns True if signature is valid, false otherwise
2545
+ *
2546
+ * @example
2547
+ * ```typescript
2548
+ * const message = new Uint8Array([1, 2, 3]);
2549
+ * const signature = keypair.sign(message);
2550
+ * const isValid = keypair.publicKey.verify(message, signature);
2551
+ * ```
2552
+ */
2553
+ verify(message, signature) {
2554
+ return verify(
2555
+ signature.toBytes(),
2556
+ message,
2557
+ this.bytes
2558
+ );
2559
+ }
2560
+ /**
2561
+ * JSON serialization (returns base58 string).
2562
+ */
2563
+ toJSON() {
2564
+ return this.toString();
2565
+ }
2566
+ };
2567
+
2568
+ // src/crypto/signature.ts
2569
+ var Signature = class _Signature {
2570
+ bytes;
2571
+ constructor(bytes) {
2572
+ if (bytes.length !== SIGNATURE_LENGTH) {
2573
+ throw CryptoError.invalidKeyLength(SIGNATURE_LENGTH, bytes.length);
2574
+ }
2575
+ this.bytes = new Uint8Array(bytes);
2576
+ }
2577
+ /**
2578
+ * Creates a Signature from raw bytes.
2579
+ *
2628
2580
  * @param bytes - 64-byte Ed25519 signature
2629
2581
  * @throws {CryptoError} If bytes length is not 64
2630
2582
  */
@@ -5989,1286 +5941,1619 @@ function createAccount(from, newAccount, lamports, space, owner) {
5989
5941
  };
5990
5942
  }
5991
5943
 
5992
- // src/rpc/errors.ts
5993
- var RpcErrorCode = /* @__PURE__ */ ((RpcErrorCode2) => {
5994
- RpcErrorCode2["REQUEST_TIMEOUT"] = "REQUEST_TIMEOUT";
5995
- RpcErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
5996
- RpcErrorCode2["CONNECTION_REFUSED"] = "CONNECTION_REFUSED";
5997
- RpcErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
5998
- RpcErrorCode2["PARSE_ERROR"] = "PARSE_ERROR";
5999
- RpcErrorCode2["INVALID_REQUEST"] = "INVALID_REQUEST";
6000
- RpcErrorCode2["METHOD_NOT_FOUND"] = "METHOD_NOT_FOUND";
6001
- RpcErrorCode2["INVALID_PARAMS"] = "INVALID_PARAMS";
6002
- RpcErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
6003
- RpcErrorCode2["TRANSACTION_REJECTED"] = "TRANSACTION_REJECTED";
6004
- RpcErrorCode2["INSUFFICIENT_FUNDS"] = "INSUFFICIENT_FUNDS";
6005
- RpcErrorCode2["ACCOUNT_NOT_FOUND"] = "ACCOUNT_NOT_FOUND";
6006
- RpcErrorCode2["BLOCKHASH_NOT_FOUND"] = "BLOCKHASH_NOT_FOUND";
6007
- RpcErrorCode2["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED";
6008
- RpcErrorCode2["NODE_UNHEALTHY"] = "NODE_UNHEALTHY";
6009
- return RpcErrorCode2;
6010
- })(RpcErrorCode || {});
6011
- var RpcError = class _RpcError extends Error {
6012
- code;
6013
- details;
6014
- retryable;
6015
- constructor(code, message, details = {}, retryable = false) {
6016
- super(message);
6017
- this.name = "RpcError";
6018
- this.code = code;
6019
- this.details = details;
6020
- this.retryable = retryable;
6021
- }
6022
- static requestTimeout(timeoutMs, details) {
6023
- return new _RpcError(
6024
- "REQUEST_TIMEOUT" /* REQUEST_TIMEOUT */,
6025
- `RPC request timed out after ${timeoutMs}ms. The node may be slow or unreachable.`,
6026
- { ...details, timeout: timeoutMs },
6027
- true
6028
- // Retryable
6029
- );
6030
- }
6031
- static networkError(message, details) {
6032
- return new _RpcError(
6033
- "NETWORK_ERROR" /* NETWORK_ERROR */,
6034
- `Network error: ${message}. Check your internet connection and node URL.`,
6035
- details,
6036
- true
6037
- // Retryable
6038
- );
6039
- }
6040
- static invalidResponse(details) {
6041
- return new _RpcError(
6042
- "INVALID_RESPONSE" /* INVALID_RESPONSE */,
6043
- "Received invalid response from RPC node. The response format is unexpected.",
6044
- details,
6045
- false
6046
- );
6047
- }
6048
- static accountNotFound(pubkey) {
6049
- return new _RpcError(
6050
- "ACCOUNT_NOT_FOUND" /* ACCOUNT_NOT_FOUND */,
6051
- `Account ${pubkey} not found on chain. It may not exist or has zero balance.`,
6052
- { pubkey },
6053
- false
5944
+ // src/transaction/message.ts
5945
+ var Message = class _Message {
5946
+ /** Message header with signature requirements */
5947
+ header;
5948
+ /** All account public keys referenced in the transaction */
5949
+ accountKeys;
5950
+ /** Transaction valid from (milliseconds since Unix epoch) */
5951
+ validFrom;
5952
+ /** Compiled instructions with account indices */
5953
+ instructions;
5954
+ /** Cached serialized bytes */
5955
+ serializedCache;
5956
+ constructor(header, accountKeys, validFrom, instructions) {
5957
+ this.header = Object.freeze({ ...header });
5958
+ this.accountKeys = Object.freeze([...accountKeys]);
5959
+ this.validFrom = validFrom;
5960
+ this.instructions = Object.freeze(
5961
+ instructions.map((ix) => Object.freeze({ ...ix }))
6054
5962
  );
6055
5963
  }
6056
- static rateLimitExceeded(details) {
6057
- return new _RpcError(
6058
- "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */,
6059
- "Rate limit exceeded. Too many requests to the RPC endpoint. Try again later or use a different endpoint.",
6060
- details,
6061
- true
6062
- // Can retry after delay
6063
- );
5964
+ /**
5965
+ * Serialize message to bytes for signing.
5966
+ * Result is cached for performance.
5967
+ */
5968
+ serialize() {
5969
+ if (!this.serializedCache) {
5970
+ this.serializedCache = this.serializeInternal();
5971
+ }
5972
+ return new Uint8Array(this.serializedCache);
6064
5973
  }
6065
- static fromRpcCode(rpcCode, message, details) {
6066
- const codeMap = {
6067
- [-32700]: "PARSE_ERROR" /* PARSE_ERROR */,
6068
- [-32600]: "INVALID_REQUEST" /* INVALID_REQUEST */,
6069
- [-32601]: "METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
6070
- [-32602]: "INVALID_PARAMS" /* INVALID_PARAMS */,
6071
- [-32603]: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
6072
- [429]: "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */
5974
+ /**
5975
+ * Deserialize a message from wire format.
5976
+ *
5977
+ * @param data - Serialized message bytes
5978
+ * @returns Deserialized Message
5979
+ */
5980
+ static deserialize(data) {
5981
+ if (data.length < 3) {
5982
+ throw new TransactionError(
5983
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
5984
+ "Insufficient data for message header"
5985
+ );
5986
+ }
5987
+ let cursor = 0;
5988
+ const header = {
5989
+ numRequiredSignatures: data[cursor++],
5990
+ numReadonlySignedAccounts: data[cursor++],
5991
+ numReadonlyUnsignedAccounts: data[cursor++]
6073
5992
  };
6074
- const code = codeMap[rpcCode] || "INTERNAL_ERROR" /* INTERNAL_ERROR */;
6075
- const retryable = rpcCode === 429 || rpcCode === -32603;
6076
- return new _RpcError(code, message, { ...details, rpcCode }, retryable);
5993
+ const [accountKeysLength, newCursor1] = deserializeCompactU162(data, cursor);
5994
+ cursor = newCursor1;
5995
+ const accountKeys = [];
5996
+ for (let i = 0; i < accountKeysLength; i++) {
5997
+ if (data.length < cursor + 32) {
5998
+ throw new TransactionError(
5999
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6000
+ `Insufficient data for account key ${i}`
6001
+ );
6002
+ }
6003
+ const keyBytes = data.slice(cursor, cursor + 32);
6004
+ accountKeys.push(PublicKey.fromBytes(keyBytes));
6005
+ cursor += 32;
6006
+ }
6007
+ if (data.length < cursor + 8) {
6008
+ throw new TransactionError(
6009
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6010
+ "Insufficient data for validFrom"
6011
+ );
6012
+ }
6013
+ const validFromBytes = data.slice(cursor, cursor + 8);
6014
+ const validFrom = BigInt.asUintN(64, new DataView(validFromBytes.buffer).getBigUint64(0));
6015
+ cursor += 8;
6016
+ const [instructionsLength, newCursor2] = deserializeCompactU162(
6017
+ data,
6018
+ cursor
6019
+ );
6020
+ cursor = newCursor2;
6021
+ const instructions = [];
6022
+ for (let i = 0; i < instructionsLength; i++) {
6023
+ if (data.length < cursor + 1) {
6024
+ throw new TransactionError(
6025
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6026
+ `Insufficient data for instruction ${i} program index`
6027
+ );
6028
+ }
6029
+ const programIdIndex = data[cursor++];
6030
+ const [accountIndexesLength, newCursor3] = deserializeCompactU162(
6031
+ data,
6032
+ cursor
6033
+ );
6034
+ cursor = newCursor3;
6035
+ const accountKeyIndexes = [];
6036
+ for (let j = 0; j < accountIndexesLength; j++) {
6037
+ if (data.length < cursor + 1) {
6038
+ throw new TransactionError(
6039
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6040
+ `Insufficient data for instruction ${i} account index ${j}`
6041
+ );
6042
+ }
6043
+ accountKeyIndexes.push(data[cursor++]);
6044
+ }
6045
+ const [dataLength, newCursor4] = deserializeCompactU162(data, cursor);
6046
+ cursor = newCursor4;
6047
+ if (data.length < cursor + dataLength) {
6048
+ throw new TransactionError(
6049
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6050
+ `Insufficient data for instruction ${i} data`
6051
+ );
6052
+ }
6053
+ const instructionData = data.slice(cursor, cursor + dataLength);
6054
+ cursor += dataLength;
6055
+ instructions.push({
6056
+ programIdIndex,
6057
+ accountKeyIndexes: Object.freeze(accountKeyIndexes),
6058
+ data: instructionData
6059
+ });
6060
+ }
6061
+ return new _Message(header, accountKeys, validFrom, instructions);
6077
6062
  }
6078
- toJSON() {
6079
- return {
6080
- code: this.code,
6081
- message: this.message,
6082
- details: this.details,
6083
- retryable: this.retryable
6084
- };
6063
+ serializeInternal() {
6064
+ const buffer = [];
6065
+ buffer.push(this.header.numRequiredSignatures);
6066
+ buffer.push(this.header.numReadonlySignedAccounts);
6067
+ buffer.push(this.header.numReadonlyUnsignedAccounts);
6068
+ this.serializeCompactArray(buffer, this.accountKeys, (buf, key) => {
6069
+ buf.push(...key.toBytes());
6070
+ });
6071
+ const validFromBuffer = new ArrayBuffer(8);
6072
+ new DataView(validFromBuffer).setBigUint64(0, this.validFrom ?? BigInt(0));
6073
+ buffer.push(...new Uint8Array(validFromBuffer));
6074
+ this.serializeCompactArray(buffer, this.instructions, (buf, ix) => {
6075
+ buf.push(ix.programIdIndex);
6076
+ this.serializeCompactArray(buf, ix.accountKeyIndexes, (b, idx) => {
6077
+ b.push(idx);
6078
+ });
6079
+ this.serializeCompactArray(buf, Array.from(ix.data), (b, byte) => {
6080
+ b.push(byte);
6081
+ });
6082
+ });
6083
+ return new Uint8Array(buffer);
6085
6084
  }
6086
- };
6087
-
6088
- // src/rpc/clients/base-client.ts
6089
- var BaseRpcClient = class {
6090
- transport;
6091
- requestId = 1;
6092
- constructor(transport) {
6093
- this.transport = transport;
6085
+ serializeCompactArray(buffer, items, serializeItem) {
6086
+ this.serializeCompactU16(buffer, items.length);
6087
+ for (const item of items) {
6088
+ serializeItem(buffer, item);
6089
+ }
6094
6090
  }
6095
- /**
6096
- * Makes a JSON-RPC 2.0 method call with type safety.
6097
- *
6098
- * Handles request serialization, response validation, and error mapping.
6099
- */
6100
- async call(method, params = []) {
6101
- const requestId = this.requestId++;
6102
- const request = {
6103
- jsonrpc: "2.0",
6104
- id: requestId,
6105
- method,
6106
- params
6107
- };
6108
- const requestBody = JSON.stringify(request);
6109
- const requestDetails = { method, params, requestId };
6110
- const data = await this.transport.request(requestBody, requestDetails);
6111
- if (!this.isValidJsonRpcResponse(data)) {
6112
- throw RpcError.invalidResponse({
6113
- ...requestDetails,
6114
- response: data
6115
- });
6091
+ serializeCompactU16(buffer, value) {
6092
+ if (value < 0 || value > 65535) {
6093
+ throw new Error(`Value out of range for compact-u16: ${value}`);
6116
6094
  }
6117
- const response = data;
6118
- if (response.error) {
6119
- throw RpcError.fromRpcCode(response.error.code, response.error.message, {
6120
- ...requestDetails,
6121
- rpcData: response.error.data
6122
- });
6095
+ if (value <= 127) {
6096
+ buffer.push(value);
6097
+ return;
6123
6098
  }
6124
- if (!("result" in response)) {
6125
- throw RpcError.invalidResponse({
6126
- ...requestDetails,
6127
- response
6128
- });
6099
+ if (value <= 16383) {
6100
+ buffer.push(value & 127 | 128);
6101
+ buffer.push(value >> 7 & 127);
6102
+ return;
6129
6103
  }
6130
- return response.result;
6104
+ buffer.push(value & 127 | 128);
6105
+ buffer.push(value >> 7 & 127 | 128);
6106
+ buffer.push(value >> 14 & 255);
6131
6107
  }
6132
6108
  /**
6133
- * Validate JSON-RPC response structure
6109
+ * Get all signers required for this message.
6134
6110
  */
6135
- isValidJsonRpcResponse(data) {
6136
- if (typeof data !== "object" || data === null) {
6137
- return false;
6138
- }
6139
- const response = data;
6140
- return response.jsonrpc === "2.0" && typeof response.id === "number" && ("result" in response || "error" in response);
6111
+ getSigners() {
6112
+ return this.accountKeys.slice(0, this.header.numRequiredSignatures);
6141
6113
  }
6142
6114
  /**
6143
- * Returns the configured RPC endpoint URL.
6115
+ * Check if a public key is a required signer.
6144
6116
  */
6145
- getUrl() {
6146
- return this.transport.getUrl();
6117
+ isSignerRequired(pubkey) {
6118
+ return this.getSigners().some((signer) => signer.equals(pubkey));
6119
+ }
6120
+ /**
6121
+ * Get the index of a signer in the signers array.
6122
+ * Returns -1 if not a signer.
6123
+ */
6124
+ getSignerIndex(pubkey) {
6125
+ return this.getSigners().findIndex((signer) => signer.equals(pubkey));
6147
6126
  }
6148
6127
  };
6149
-
6150
- // src/utils.ts
6151
- function toBase64(bytes) {
6152
- if (typeof btoa !== "undefined") {
6153
- const chunkSize = 8192;
6154
- let result = "";
6155
- for (let i = 0; i < bytes.length; i += chunkSize) {
6156
- const chunk = bytes.slice(i, i + chunkSize);
6157
- result += String.fromCharCode(...chunk);
6158
- }
6159
- return btoa(result);
6128
+ function deserializeCompactU162(data, currentCursor) {
6129
+ let cursor = currentCursor;
6130
+ if (cursor >= data.length) {
6131
+ throw new TransactionError(
6132
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6133
+ "Insufficient data for compact-u16"
6134
+ );
6160
6135
  }
6161
- if (typeof Buffer !== "undefined") {
6162
- return Buffer.from(bytes).toString("base64");
6136
+ const firstByte = data[cursor++];
6137
+ if ((firstByte & 128) === 0) {
6138
+ return [firstByte, cursor];
6163
6139
  }
6164
- throw new Error("No base64 encoding available in this environment");
6165
- }
6166
- function fromBase64(base64) {
6167
- if (typeof atob !== "undefined") {
6168
- const binary = atob(base64);
6169
- const bytes = new Uint8Array(binary.length);
6170
- for (let i = 0; i < binary.length; i++) {
6171
- bytes[i] = binary.charCodeAt(i);
6172
- }
6173
- return bytes;
6140
+ if (cursor >= data.length) {
6141
+ throw new TransactionError(
6142
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6143
+ "Incomplete compact-u16 encoding"
6144
+ );
6174
6145
  }
6175
- if (typeof Buffer !== "undefined") {
6176
- return new Uint8Array(Buffer.from(base64, "base64"));
6146
+ const secondByte = data[cursor++];
6147
+ if ((secondByte & 128) === 0) {
6148
+ return [firstByte & 127 | secondByte << 7, cursor];
6177
6149
  }
6178
- throw new Error("No base64 decoding available in this environment");
6179
- }
6180
- function sleep(ms) {
6181
- return new Promise((resolve) => setTimeout(resolve, ms));
6182
- }
6183
- function calculateBackoff(attempt, baseMs = 1e3, maxMs = 3e4) {
6184
- const exponentialDelay = baseMs * 2 ** attempt;
6185
- const jitter = Math.random() * 0.3 * exponentialDelay;
6186
- return Math.min(exponentialDelay + jitter, maxMs);
6187
- }
6188
- function getDevnetUrl() {
6189
- return URL_DEVNET;
6190
- }
6191
- function getTestnetUrl() {
6192
- return URL_TESTNET;
6193
- }
6194
- function getMainnetUrl() {
6195
- return URL_MAINNET;
6196
- }
6197
- function getLocalnetUrl() {
6198
- return URL_LOCALNET;
6150
+ if (cursor >= data.length) {
6151
+ throw new TransactionError(
6152
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6153
+ "Incomplete compact-u16 encoding"
6154
+ );
6155
+ }
6156
+ const thirdByte = data[cursor++];
6157
+ const value = firstByte & 127 | (secondByte & 127) << 7 | thirdByte << 14;
6158
+ return [value, cursor];
6199
6159
  }
6200
6160
 
6201
- // src/rpc/clients/query-client.ts
6202
- var QueryRpcClient = class extends BaseRpcClient {
6161
+ // src/transaction/transaction.ts
6162
+ var Transaction = class _Transaction {
6163
+ /** The unsigned message */
6164
+ message;
6165
+ /** Signatures (64 bytes each), aligned with message.header.numRequiredSignatures */
6166
+ signatures;
6167
+ // Private constructor - use static factories
6168
+ constructor(message, signatures) {
6169
+ this.message = message;
6170
+ this.signatures = signatures.map((sig) => new Uint8Array(sig));
6171
+ if (signatures.length !== message.header.numRequiredSignatures) {
6172
+ throw new TransactionError(
6173
+ "INVALID_SIGNATURE" /* INVALID_SIGNATURE */,
6174
+ `Signature count (${signatures.length}) doesn't match required signers (${message.header.numRequiredSignatures})`
6175
+ );
6176
+ }
6177
+ }
6203
6178
  /**
6204
- * Get the latest blockhash from the blockchain
6179
+ * Create an unsigned transaction from a message.
6180
+ * All signature slots are initialized to zero.
6181
+ *
6182
+ * @internal - Users should use TransactionBuilder instead
6205
6183
  */
6206
- async getLatestBlockhash() {
6207
- const result = await this.call(
6208
- "getLatestBlockhash",
6209
- []
6184
+ static fromMessage(message) {
6185
+ const numSignatures = message.header.numRequiredSignatures;
6186
+ const signatures = Array.from(
6187
+ { length: numSignatures },
6188
+ () => new Uint8Array(SIGNATURE_LENGTH)
6210
6189
  );
6211
- return Blockhash.fromString(result.value.blockhash);
6190
+ return new _Transaction(message, signatures);
6212
6191
  }
6213
6192
  /**
6214
- * Get the balance of an account
6193
+ * Create transaction from message and existing signatures.
6194
+ * @internal
6215
6195
  */
6216
- async getBalance(pubkey) {
6217
- const result = await this.call("getBalance", [
6218
- { address: pubkey.toString() }
6219
- ]);
6220
- return BigInt(result.value);
6196
+ static fromMessageAndSignatures(message, signatures) {
6197
+ return new _Transaction(message, signatures);
6221
6198
  }
6222
6199
  /**
6223
- * Get detailed information about an account
6200
+ * Deserialize a transaction from wire format.
6224
6201
  */
6225
- async getAccountInfo(pubkey) {
6226
- const result = await this.call("getAccountInfo", [{ address: pubkey.toString(), encoding: "base64" }]);
6227
- if (!result.value) {
6228
- return null;
6202
+ static deserialize(data) {
6203
+ if (data.length === 0) {
6204
+ throw new TransactionError(
6205
+ "SERIALIZATION_FAILED" /* SERIALIZATION_FAILED */,
6206
+ "Cannot deserialize empty transaction data"
6207
+ );
6229
6208
  }
6230
- return {
6231
- balance: BigInt(result.value.balance),
6232
- owner: PublicKey.fromString(result.value.owner),
6233
- data: fromBase64(result.value.data),
6234
- executable: result.value.executable,
6235
- rentEpoch: BigInt(result.value.rentEpoch)
6236
- };
6237
- }
6238
- /**
6239
- * Get the current block height
6240
- */
6241
- async getBlockHeight() {
6242
- const result = await this.call("getBlockHeight", []);
6243
- return BigInt(result);
6244
- }
6245
- /**
6246
- * Get detailed information about a transaction
6247
- */
6248
- async getTransaction(signature) {
6249
- const result = await this.call("getTransaction", [signature]);
6250
- if (!result) {
6251
- return null;
6209
+ let cursor = 0;
6210
+ const [signaturesLength, newCursor] = deserializeCompactU16(data, cursor);
6211
+ cursor = newCursor;
6212
+ const signatures = [];
6213
+ for (let i = 0; i < signaturesLength; i++) {
6214
+ if (data.length < cursor + SIGNATURE_LENGTH) {
6215
+ throw new TransactionError(
6216
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6217
+ `Insufficient data for signature ${i}: need ${SIGNATURE_LENGTH} bytes at offset ${cursor}`
6218
+ );
6219
+ }
6220
+ const signature = data.slice(cursor, cursor + SIGNATURE_LENGTH);
6221
+ signatures.push(signature);
6222
+ cursor += SIGNATURE_LENGTH;
6252
6223
  }
6253
- return {
6254
- signature,
6255
- slot: BigInt(result.slot),
6256
- blockTime: result.blockTime ? BigInt(result.blockTime) : void 0,
6257
- err: result.err
6258
- };
6224
+ if (cursor >= data.length) {
6225
+ throw new TransactionError(
6226
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6227
+ "No message data found after signatures"
6228
+ );
6229
+ }
6230
+ const messageBytes = data.slice(cursor);
6231
+ const message = Message.deserialize(messageBytes);
6232
+ return new _Transaction(message, signatures);
6233
+ }
6234
+ getMessage() {
6235
+ return this.message;
6259
6236
  }
6260
6237
  /**
6261
- * Get the total number of transactions processed since genesis
6238
+ * Sign the transaction with a keypair.
6239
+ * Returns a NEW Transaction instance.
6240
+ *
6241
+ * @param keypair - Keypair to sign with
6242
+ * @returns New Transaction instance with signature added
6243
+ *
6244
+ * @example
6245
+ * ```typescript
6246
+ * const signedTx = tx.sign(keypair);
6247
+ * await client.sendTransaction(signedTx.serialize());
6248
+ * ```
6262
6249
  */
6263
- async getTransactionCount() {
6264
- const result = await this.call("getTransactionCount", []);
6265
- return BigInt(result);
6250
+ sign(keypair) {
6251
+ const messageBytes = this.message.serialize();
6252
+ const signature = keypair.sign(messageBytes);
6253
+ return this.addSignatureForPubkey(keypair.publicKey, signature);
6266
6254
  }
6267
6255
  /**
6268
- * Get the status of multiple transaction signatures
6256
+ * Sign with multiple keypairs at once.
6257
+ * Returns a NEW Transaction instance.
6258
+ *
6259
+ * @example
6260
+ * ```typescript
6261
+ * const signed = tx.signAll([keypair1, keypair2, keypair3]);
6262
+ * ```
6269
6263
  */
6270
- async getSignatureStatuses(signatures) {
6271
- const result = await this.call("getSignatureStatuses", [signatures]);
6272
- return result.value.map((status) => {
6273
- if (!status) {
6274
- return null;
6275
- }
6276
- return {
6277
- slot: BigInt(status.slot),
6278
- confirmations: status.confirmations,
6279
- err: status.err
6280
- };
6281
- });
6264
+ signAll(keypairs) {
6265
+ let result = this;
6266
+ for (const keypair of keypairs) {
6267
+ result = result.sign(keypair);
6268
+ }
6269
+ return result;
6282
6270
  }
6283
6271
  /**
6284
- * Get epoch information
6272
+ * Sign the transaction with a Signer interface (async).
6273
+ * Returns a NEW Transaction instance.
6274
+ *
6275
+ * @example
6276
+ * ```typescript
6277
+ * const signedTx = await tx.signWith(browserWallet);
6278
+ * ```
6285
6279
  */
6286
- async getEpochInfo() {
6287
- const result = await this.call("getEpochInfo", []);
6288
- return {
6289
- epoch: BigInt(result.epoch),
6290
- slotIndex: BigInt(result.slotIndex),
6291
- slotsInEpoch: BigInt(result.slotsInEpoch),
6292
- absoluteSlot: BigInt(result.absoluteSlot),
6293
- blockHeight: BigInt(result.blockHeight),
6294
- transactionCount: result.transactionCount ? BigInt(result.transactionCount) : void 0
6295
- };
6280
+ async signWith(signer) {
6281
+ const pubkey = await signer.getPublicKey();
6282
+ const messageBytes = this.message.serialize();
6283
+ const signature = await signer.signMessage(messageBytes);
6284
+ return this.addSignatureForPubkey(pubkey, signature);
6296
6285
  }
6297
6286
  /**
6298
- * Get the health status of the node
6287
+ * Sign with multiple signers.
6288
+ * Returns a NEW Transaction instance.
6299
6289
  */
6300
- async getHealth() {
6301
- const result = await this.call("getHealth", []);
6290
+ async signAllWith(signers) {
6291
+ let result = this;
6292
+ for (const signer of signers) {
6293
+ result = await result.signWith(signer);
6294
+ }
6302
6295
  return result;
6303
6296
  }
6304
- };
6305
-
6306
- // src/rpc/clients/transaction-client.ts
6307
- var TransactionRpcClient = class extends BaseRpcClient {
6308
6297
  /**
6309
- * Submit a signed transaction to the blockchain
6298
+ * Partially sign the transaction (for multi-sig transactions).
6299
+ * Returns a NEW Transaction instance.
6300
+ *
6301
+ * @example
6302
+ * ```typescript
6303
+ * const signedTx = tx
6304
+ * .partialSign(signer1)
6305
+ * .partialSign(signer2);
6306
+ * ```
6310
6307
  */
6311
- async sendTransaction(transaction, options) {
6312
- const base64Tx = toBase64(transaction);
6313
- const config = {
6314
- encoding: "base64",
6315
- skipPreflight: options?.skipPreflight ?? false,
6316
- maxRetries: options?.maxRetries ?? 5
6317
- };
6318
- const signature = await this.call("sendTransaction", [
6319
- base64Tx,
6320
- config
6321
- ]);
6322
- return signature;
6308
+ partialSign(keypair) {
6309
+ return this.sign(keypair);
6323
6310
  }
6324
6311
  /**
6325
- * Request an airdrop of tokens to an account (devnet/testnet only)
6312
+ * Partially sign with a Signer interface (async).
6313
+ * Returns a NEW Transaction instance.
6326
6314
  */
6327
- async requestAirdrop(pubkey, amount) {
6328
- const signature = await this.call("requestAirdrop", [
6329
- pubkey.toString(),
6330
- Number(amount)
6331
- ]);
6332
- return signature;
6333
- }
6334
- };
6335
-
6336
- // src/rpc/clients/client.ts
6337
- var RialoClient = class {
6338
- queryClient;
6339
- transactionClient;
6340
- transport;
6341
- constructor(transport) {
6342
- this.transport = transport;
6343
- this.queryClient = new QueryRpcClient(transport);
6344
- this.transactionClient = new TransactionRpcClient(transport);
6315
+ async partialSignWith(signer) {
6316
+ return this.signWith(signer);
6345
6317
  }
6346
6318
  /**
6347
- * Returns the configured RPC endpoint URL.
6319
+ * Add a signature at a specific index.
6320
+ * Returns a NEW Transaction instance.
6321
+ *
6322
+ * Most users should use sign() or signAll() instead.
6348
6323
  */
6349
- getUrl() {
6350
- return this.transport.getUrl();
6324
+ addSignature(index, signature) {
6325
+ if (index < 0 || index >= this.signatures.length) {
6326
+ throw new TransactionError(
6327
+ "SIGNATURE_OUT_OF_BOUNDS" /* SIGNATURE_OUT_OF_BOUNDS */,
6328
+ `Signature index ${index} out of bounds (must be 0-${this.signatures.length - 1})`
6329
+ );
6330
+ }
6331
+ const sigBytes = signature instanceof Uint8Array ? signature : signature.toBytes();
6332
+ if (sigBytes.length !== SIGNATURE_LENGTH) {
6333
+ throw new TransactionError(
6334
+ "INVALID_SIGNATURE" /* INVALID_SIGNATURE */,
6335
+ `Signature must be ${SIGNATURE_LENGTH} bytes, got ${sigBytes.length}`
6336
+ );
6337
+ }
6338
+ const newSignatures = this.signatures.map(
6339
+ (sig, i) => i === index ? new Uint8Array(sigBytes) : new Uint8Array(sig)
6340
+ );
6341
+ return new _Transaction(this.message, newSignatures);
6351
6342
  }
6352
6343
  /**
6353
- * Retrieves the latest blockhash from the blockchain.
6344
+ * Add a signature for a specific public key.
6345
+ * Returns a NEW Transaction instance.
6354
6346
  *
6355
- * Required for transaction creation and replay protection.
6347
+ * Most users should use sign() or signAll() instead.
6356
6348
  */
6357
- async getLatestBlockhash() {
6358
- return await this.queryClient.getLatestBlockhash();
6349
+ addSignatureForPubkey(pubkey, signature) {
6350
+ const signerIndex = this.message.getSignerIndex(pubkey);
6351
+ if (signerIndex === -1) {
6352
+ throw TransactionError.signerNotFound(pubkey.toString());
6353
+ }
6354
+ return this.addSignature(signerIndex, signature);
6359
6355
  }
6360
6356
  /**
6361
- * Retrieves the balance of an account in kelvins (smallest unit).
6357
+ * Check if transaction is fully signed (all signatures present).
6362
6358
  */
6363
- async getBalance(pubkey) {
6364
- return await this.queryClient.getBalance(pubkey);
6359
+ isSigned() {
6360
+ return this.signatures.every((sig) => sig.some((byte) => byte !== 0));
6365
6361
  }
6366
6362
  /**
6367
- * Retrieves detailed information about an account.
6368
- *
6369
- * @returns Account info or null if account doesn't exist
6363
+ * Check if a specific signature slot is filled.
6370
6364
  */
6371
- async getAccountInfo(pubkey) {
6372
- return await this.queryClient.getAccountInfo(pubkey);
6365
+ isSignaturePresent(index) {
6366
+ if (index < 0 || index >= this.signatures.length) {
6367
+ return false;
6368
+ }
6369
+ return this.signatures[index].some((byte) => byte !== 0);
6373
6370
  }
6374
6371
  /**
6375
- * Retrieves the current block height.
6372
+ * Get all signatures (returns copies to prevent mutation).
6376
6373
  */
6377
- async getBlockHeight() {
6378
- return await this.queryClient.getBlockHeight();
6374
+ getSignatures() {
6375
+ return this.signatures.map((sig) => new Uint8Array(sig));
6379
6376
  }
6380
6377
  /**
6381
- * Retrieves detailed information about a transaction.
6382
- *
6383
- * @returns Transaction info or null if transaction not found
6378
+ * Get a specific signature (returns copy).
6384
6379
  */
6385
- async getTransaction(signature) {
6386
- return await this.queryClient.getTransaction(signature);
6380
+ getSignature(index) {
6381
+ if (index < 0 || index >= this.signatures.length) {
6382
+ throw new TransactionError(
6383
+ "SIGNATURE_OUT_OF_BOUNDS" /* SIGNATURE_OUT_OF_BOUNDS */,
6384
+ `Signature index ${index} out of bounds`
6385
+ );
6386
+ }
6387
+ return new Uint8Array(this.signatures[index]);
6387
6388
  }
6388
6389
  /**
6389
- * Retrieves the total number of transactions processed since genesis.
6390
+ * Get a specific signature for a public key.
6390
6391
  */
6391
- async getTransactionCount() {
6392
- return await this.queryClient.getTransactionCount();
6392
+ getSignatureForPubkey(pubkey) {
6393
+ const signerIndex = this.message.getSignerIndex(pubkey);
6394
+ if (signerIndex === -1) {
6395
+ throw TransactionError.signerNotFound(pubkey.toString());
6396
+ }
6397
+ return this.getSignature(signerIndex);
6393
6398
  }
6394
6399
  /**
6395
- * Retrieves the status of multiple transaction signatures.
6400
+ * Get required signers for this transaction.
6396
6401
  */
6397
- async getSignatureStatuses(signatures) {
6398
- return await this.queryClient.getSignatureStatuses(signatures);
6402
+ getSigners() {
6403
+ return this.message.getSigners();
6399
6404
  }
6400
6405
  /**
6401
- * Retrieves current epoch information.
6406
+ * Get the number of required signatures.
6402
6407
  */
6403
- async getEpochInfo() {
6404
- return await this.queryClient.getEpochInfo();
6408
+ getRequiredSignatureCount() {
6409
+ return this.message.header.numRequiredSignatures;
6405
6410
  }
6406
6411
  /**
6407
- * Checks the health status of the RPC node.
6412
+ * Throw an error if the transaction is not fully signed.
6408
6413
  *
6409
- * @returns "ok" if healthy, error message otherwise
6410
- */
6411
- async getHealth() {
6412
- return await this.queryClient.getHealth();
6413
- }
6414
- /**
6415
- * Submits a signed transaction to the blockchain.
6414
+ * @throws {TransactionError} If transaction is not fully signed
6416
6415
  *
6417
- * @param transaction - Serialized signed transaction bytes
6418
- * @param options - Transaction submission options
6419
- * @returns Transaction signature
6416
+ * @example
6417
+ * ```typescript
6418
+ * signedTx.ensureSigned(); // Throws if not signed
6419
+ * await client.sendTransaction(signedTx.serialize());
6420
+ * ```
6420
6421
  */
6421
- async sendTransaction(transaction, options) {
6422
- return await this.transactionClient.sendTransaction(transaction, options);
6422
+ ensureSigned() {
6423
+ if (!this.isSigned()) {
6424
+ const missingIndices = this.signatures.map((sig, i) => ({ sig, i })).filter(({ sig }) => !sig.some((byte) => byte !== 0)).map(({ i }) => i);
6425
+ const signers = this.getSigners();
6426
+ const missingSigners = missingIndices.map((i) => signers[i].toString());
6427
+ throw new TransactionError(
6428
+ "MISSING_SIGNATURE" /* MISSING_SIGNATURE */,
6429
+ `Transaction is not fully signed. Missing signatures for: ${missingSigners.join(", ")}`,
6430
+ { missingIndices, missingSigners }
6431
+ );
6432
+ }
6423
6433
  }
6424
6434
  /**
6425
- * Requests an airdrop of tokens to an account.
6426
- *
6427
- * **Note**: Only available on devnet and testnet.
6428
- *
6429
- * @param pubkey - Account to receive the airdrop
6430
- * @param amount - Amount in kelvins (smallest unit)
6431
- * @returns Transaction signature
6435
+ * Serialize transaction to wire format.
6432
6436
  */
6433
- async requestAirdrop(pubkey, amount) {
6434
- return await this.transactionClient.requestAirdrop(pubkey, amount);
6437
+ serialize() {
6438
+ const compactU16Size = this.signatures.length < 128 ? 1 : 2;
6439
+ const sigsSize = compactU16Size + this.signatures.length * SIGNATURE_LENGTH;
6440
+ const messageBytes = this.message.serialize();
6441
+ const totalSize = sigsSize + messageBytes.length;
6442
+ const buffer = new Uint8Array(totalSize);
6443
+ let offset = 0;
6444
+ offset = writeCompactU16(buffer, offset, this.signatures.length);
6445
+ for (const sig of this.signatures) {
6446
+ buffer.set(sig, offset);
6447
+ offset += SIGNATURE_LENGTH;
6448
+ }
6449
+ buffer.set(messageBytes, offset);
6450
+ return buffer;
6435
6451
  }
6436
6452
  };
6437
6453
 
6438
- // src/rpc/http-transport.ts
6439
- var DEFAULT_CONFIG = {
6440
- timeout: 3e4,
6441
- // 30 seconds
6442
- maxRetries: 3,
6443
- retryBaseDelay: 1e3,
6444
- // 1 second
6445
- retryMaxDelay: 3e4,
6446
- // 30 seconds
6447
- headers: {}
6448
- };
6449
- var HttpTransport = class {
6450
- url;
6451
- config;
6452
- constructor(url, config = {}) {
6453
- this.url = url;
6454
- this.config = { ...DEFAULT_CONFIG, ...config };
6454
+ // src/transaction/transaction-builder.ts
6455
+ var TransactionBuilder = class _TransactionBuilder {
6456
+ payer;
6457
+ validFrom;
6458
+ instructions = [];
6459
+ constructor() {
6455
6460
  }
6456
6461
  /**
6457
- * Makes an HTTP request with automatic retry logic.
6458
- *
6459
- * Retries are attempted for network errors and server errors (5xx).
6460
- * Uses exponential backoff between retry attempts.
6462
+ * Create a new transaction builder.
6461
6463
  */
6462
- async request(body, requestDetails = {}) {
6463
- let lastError;
6464
- for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
6465
- try {
6466
- return await this.makeRequest(body, requestDetails, attempt);
6467
- } catch (error) {
6468
- lastError = error;
6469
- if (error instanceof RpcError && !error.retryable) {
6470
- throw error;
6471
- }
6472
- if (attempt === this.config.maxRetries) {
6473
- throw error;
6474
- }
6475
- const delay = calculateBackoff(
6476
- attempt,
6477
- this.config.retryBaseDelay,
6478
- this.config.retryMaxDelay
6479
- );
6480
- await sleep(delay);
6481
- }
6482
- }
6483
- throw lastError;
6464
+ static create() {
6465
+ return new _TransactionBuilder();
6484
6466
  }
6485
6467
  /**
6486
- * Make a single HTTP request with timeout
6468
+ * Set the fee payer for this transaction.
6469
+ *
6470
+ * The payer will be the first account and must sign the transaction.
6471
+ * The payer pays for transaction fees.
6472
+ *
6473
+ * @param payer - Public key of the fee payer
6487
6474
  */
6488
- async makeRequest(body, requestDetails, attempt) {
6489
- const controller = new AbortController();
6490
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
6491
- try {
6492
- const options = {
6493
- method: "POST",
6494
- headers: {
6495
- "Content-Type": "application/json",
6496
- ...this.config.headers
6497
- },
6498
- body,
6499
- signal: controller.signal
6500
- };
6501
- const response = await fetch(this.url, options);
6502
- if (!response.ok) {
6503
- throw await this.handleHttpError(response, requestDetails, attempt);
6504
- }
6505
- const data = await response.json();
6506
- return data;
6507
- } catch (error) {
6508
- if (error instanceof Error && error.name === "AbortError") {
6509
- throw RpcError.requestTimeout(this.config.timeout, {
6510
- ...requestDetails,
6511
- url: this.url,
6512
- attempts: attempt + 1
6513
- });
6514
- }
6515
- if (error instanceof TypeError) {
6516
- throw RpcError.networkError(error.message, {
6517
- ...requestDetails,
6518
- url: this.url,
6519
- attempts: attempt + 1,
6520
- cause: error.message
6521
- });
6522
- }
6523
- if (error instanceof RpcError) {
6524
- throw error;
6525
- }
6526
- throw RpcError.networkError("Unknown network error", {
6527
- ...requestDetails,
6528
- url: this.url,
6529
- attempts: attempt + 1,
6530
- cause: error instanceof Error ? error.message : String(error)
6531
- });
6532
- } finally {
6533
- clearTimeout(timeoutId);
6534
- }
6475
+ setPayer(payer) {
6476
+ this.payer = payer;
6477
+ return this;
6535
6478
  }
6536
6479
  /**
6537
- * Handle HTTP error responses
6480
+ * Set the Transaction valid from.
6481
+ *
6482
+ * This is the time the transaction is valid from, in milliseconds since Unix epoch.
6483
+ * It can be used for additional replay protection or auditing.
6484
+ *
6485
+ * @param validFrom - Transaction valid from in milliseconds since Unix epoch
6538
6486
  */
6539
- async handleHttpError(response, requestDetails, attempt) {
6540
- const status = response.status;
6541
- if (status === 429) {
6542
- return RpcError.rateLimitExceeded({
6543
- ...requestDetails,
6544
- httpStatus: status,
6545
- url: this.url,
6546
- attempts: attempt + 1
6547
- });
6548
- }
6549
- if (status >= 500) {
6550
- return RpcError.networkError(`Server error: ${status}`, {
6551
- ...requestDetails,
6552
- httpStatus: status,
6553
- url: this.url,
6554
- attempts: attempt + 1
6555
- });
6556
- }
6557
- let message = `HTTP ${status}: ${response.statusText}`;
6558
- try {
6559
- const errorData = await response.json();
6560
- if (errorData && typeof errorData === "object" && "message" in errorData) {
6561
- message = String(errorData.message);
6562
- }
6563
- } catch {
6564
- }
6565
- return new RpcError(
6566
- "NETWORK_ERROR" /* NETWORK_ERROR */,
6567
- message,
6568
- {
6569
- ...requestDetails,
6570
- httpStatus: status,
6571
- url: this.url,
6572
- attempts: attempt + 1
6573
- },
6574
- false
6575
- // 4xx errors are not retryable
6576
- );
6487
+ setValidFrom(validFrom) {
6488
+ this.validFrom = validFrom;
6489
+ return this;
6577
6490
  }
6578
6491
  /**
6579
- * Returns the configured RPC endpoint URL.
6492
+ * Add an instruction to the transaction.
6493
+ *
6494
+ * @param instruction - Instruction to add
6580
6495
  */
6581
- getUrl() {
6582
- return this.url;
6583
- }
6584
- };
6585
-
6586
- // src/rpc/index.ts
6587
- function createRialoClient(url, config) {
6588
- const transport = new HttpTransport(url, config);
6589
- return new RialoClient(transport);
6590
- }
6591
-
6592
- // src/transaction/message.ts
6593
- var Message = class _Message {
6594
- /** Message header with signature requirements */
6595
- header;
6596
- /** All account public keys referenced in the transaction */
6597
- accountKeys;
6598
- /** Recent blockhash for replay protection */
6599
- recentBlockhash;
6600
- /** Transaction creation timestamp (milliseconds since Unix epoch) */
6601
- txCreationTime;
6602
- /** Compiled instructions with account indices */
6603
- instructions;
6604
- /** Cached serialized bytes */
6605
- serializedCache;
6606
- constructor(header, accountKeys, recentBlockhash, txCreationTime, instructions) {
6607
- this.header = Object.freeze({ ...header });
6608
- this.accountKeys = Object.freeze([...accountKeys]);
6609
- this.recentBlockhash = recentBlockhash;
6610
- this.txCreationTime = txCreationTime;
6611
- this.instructions = Object.freeze(
6612
- instructions.map((ix) => Object.freeze({ ...ix }))
6613
- );
6496
+ addInstruction(instruction) {
6497
+ this.instructions.push(instruction);
6498
+ return this;
6614
6499
  }
6615
6500
  /**
6616
- * Serialize message to bytes for signing.
6617
- * Result is cached for performance.
6501
+ * Add multiple instructions at once.
6502
+ *
6503
+ * @param instructions - Array of instructions to add
6618
6504
  */
6619
- serialize() {
6620
- if (!this.serializedCache) {
6621
- this.serializedCache = this.serializeInternal();
6622
- }
6623
- return new Uint8Array(this.serializedCache);
6505
+ addInstructions(instructions) {
6506
+ this.instructions.push(...instructions);
6507
+ return this;
6624
6508
  }
6625
6509
  /**
6626
- * Deserialize a message from wire format.
6510
+ * Build the transaction (unsigned).
6627
6511
  *
6628
- * @param data - Serialized message bytes
6629
- * @returns Deserialized Message
6630
- */
6631
- static deserialize(data) {
6632
- if (data.length < 3) {
6633
- throw new TransactionError(
6634
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6635
- "Insufficient data for message header"
6636
- );
6637
- }
6638
- let cursor = 0;
6639
- const header = {
6640
- numRequiredSignatures: data[cursor++],
6641
- numReadonlySignedAccounts: data[cursor++],
6642
- numReadonlyUnsignedAccounts: data[cursor++]
6643
- };
6644
- const [accountKeysLength, newCursor1] = deserializeCompactU162(data, cursor);
6645
- cursor = newCursor1;
6646
- const accountKeys = [];
6647
- for (let i = 0; i < accountKeysLength; i++) {
6648
- if (data.length < cursor + 32) {
6649
- throw new TransactionError(
6650
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6651
- `Insufficient data for account key ${i}`
6652
- );
6653
- }
6654
- const keyBytes = data.slice(cursor, cursor + 32);
6655
- accountKeys.push(PublicKey.fromBytes(keyBytes));
6656
- cursor += 32;
6657
- }
6658
- if (data.length < cursor + 32) {
6512
+ * Returns an unsigned Transaction that's ready to be signed.
6513
+ *
6514
+ * @returns Unsigned Transaction
6515
+ * @throws {TransactionError} If payer, valid_from, or instructions are missing
6516
+ *
6517
+ * @example
6518
+ * ```typescript
6519
+ * const tx = builder.build();
6520
+ * const signedTx = tx.sign(keypair);
6521
+ * ```
6522
+ */
6523
+ build() {
6524
+ if (!this.payer) {
6659
6525
  throw new TransactionError(
6660
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6661
- "Insufficient data for blockhash"
6526
+ "INVALID_ACCOUNT_META" /* INVALID_ACCOUNT_META */,
6527
+ "Transaction must have a fee payer. Use setPayer() to set the fee payer."
6662
6528
  );
6663
6529
  }
6664
- const recentBlockhash = Blockhash.fromBytes(
6665
- data.slice(cursor, cursor + 32)
6666
- );
6667
- cursor += 32;
6668
- if (data.length < cursor + 8) {
6530
+ if (!this.validFrom) {
6669
6531
  throw new TransactionError(
6670
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6671
- "Insufficient data for TxCreationTime"
6532
+ "INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
6533
+ "Transaction must have a valid from. Use setValidFrom() to set the valid from."
6672
6534
  );
6673
6535
  }
6674
- const txCreationTimeBytes = data.slice(cursor, cursor + 8);
6675
- const txCreationTime = BigInt.asUintN(64, new DataView(txCreationTimeBytes.buffer).getBigUint64(0));
6676
- cursor += 8;
6677
- const [instructionsLength, newCursor2] = deserializeCompactU162(
6678
- data,
6679
- cursor
6680
- );
6681
- cursor = newCursor2;
6682
- const instructions = [];
6683
- for (let i = 0; i < instructionsLength; i++) {
6684
- if (data.length < cursor + 1) {
6536
+ if (this.instructions.length === 0) {
6537
+ throw TransactionError.noInstructions();
6538
+ }
6539
+ const accountTable = new AccountMetaTable();
6540
+ accountTable.add({
6541
+ pubkey: this.payer,
6542
+ isSigner: true,
6543
+ isWritable: true
6544
+ });
6545
+ for (const instruction of this.instructions) {
6546
+ accountTable.addAll(instruction.accounts);
6547
+ accountTable.add({
6548
+ pubkey: instruction.programId,
6549
+ isSigner: false,
6550
+ isWritable: false
6551
+ });
6552
+ }
6553
+ const accountKeys = accountTable.getPublicKeys();
6554
+ const header = accountTable.getHeader();
6555
+ const compiledInstructions = this.instructions.map((instruction) => {
6556
+ const programIdIndex = accountTable.getIndex(instruction.programId);
6557
+ if (programIdIndex === -1) {
6685
6558
  throw new TransactionError(
6686
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6687
- `Insufficient data for instruction ${i} program index`
6559
+ "INVALID_INSTRUCTION" /* INVALID_INSTRUCTION */,
6560
+ `Program ID ${instruction.programId.toString()} not found in account table`
6688
6561
  );
6689
6562
  }
6690
- const programIdIndex = data[cursor++];
6691
- const [accountIndexesLength, newCursor3] = deserializeCompactU162(
6692
- data,
6693
- cursor
6694
- );
6695
- cursor = newCursor3;
6696
- const accountKeyIndexes = [];
6697
- for (let j = 0; j < accountIndexesLength; j++) {
6698
- if (data.length < cursor + 1) {
6563
+ const accountKeyIndexes = instruction.accounts.map((meta) => {
6564
+ const index = accountTable.getIndex(meta.pubkey);
6565
+ if (index === -1) {
6699
6566
  throw new TransactionError(
6700
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6701
- `Insufficient data for instruction ${i} account index ${j}`
6567
+ "INVALID_INSTRUCTION" /* INVALID_INSTRUCTION */,
6568
+ `Account ${meta.pubkey.toString()} not found in account table`
6702
6569
  );
6703
6570
  }
6704
- accountKeyIndexes.push(data[cursor++]);
6705
- }
6706
- const [dataLength, newCursor4] = deserializeCompactU162(data, cursor);
6707
- cursor = newCursor4;
6708
- if (data.length < cursor + dataLength) {
6709
- throw new TransactionError(
6710
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6711
- `Insufficient data for instruction ${i} data`
6712
- );
6713
- }
6714
- const instructionData = data.slice(cursor, cursor + dataLength);
6715
- cursor += dataLength;
6716
- instructions.push({
6571
+ return index;
6572
+ });
6573
+ const compiled = {
6717
6574
  programIdIndex,
6718
6575
  accountKeyIndexes: Object.freeze(accountKeyIndexes),
6719
- data: instructionData
6720
- });
6721
- }
6722
- return new _Message(header, accountKeys, recentBlockhash, txCreationTime, instructions);
6723
- }
6724
- serializeInternal() {
6725
- const buffer = [];
6726
- buffer.push(this.header.numRequiredSignatures);
6727
- buffer.push(this.header.numReadonlySignedAccounts);
6728
- buffer.push(this.header.numReadonlyUnsignedAccounts);
6729
- this.serializeCompactArray(buffer, this.accountKeys, (buf, key) => {
6730
- buf.push(...key.toBytes());
6731
- });
6732
- buffer.push(...this.recentBlockhash.toBytes());
6733
- const txCreationTimeBuffer = new ArrayBuffer(8);
6734
- new DataView(txCreationTimeBuffer).setBigUint64(0, this.txCreationTime ?? BigInt(0));
6735
- buffer.push(...new Uint8Array(txCreationTimeBuffer));
6736
- this.serializeCompactArray(buffer, this.instructions, (buf, ix) => {
6737
- buf.push(ix.programIdIndex);
6738
- this.serializeCompactArray(buf, ix.accountKeyIndexes, (b, idx) => {
6739
- b.push(idx);
6740
- });
6741
- this.serializeCompactArray(buf, Array.from(ix.data), (b, byte) => {
6742
- b.push(byte);
6743
- });
6576
+ data: instruction.data
6577
+ };
6578
+ return compiled;
6744
6579
  });
6745
- return new Uint8Array(buffer);
6580
+ const message = new Message(
6581
+ header,
6582
+ accountKeys,
6583
+ this.validFrom,
6584
+ compiledInstructions
6585
+ );
6586
+ return Transaction.fromMessage(message);
6746
6587
  }
6747
- serializeCompactArray(buffer, items, serializeItem) {
6748
- this.serializeCompactU16(buffer, items.length);
6749
- for (const item of items) {
6750
- serializeItem(buffer, item);
6751
- }
6588
+ };
6589
+
6590
+ // src/rpc/errors.ts
6591
+ var RpcErrorCode = /* @__PURE__ */ ((RpcErrorCode2) => {
6592
+ RpcErrorCode2["REQUEST_TIMEOUT"] = "REQUEST_TIMEOUT";
6593
+ RpcErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
6594
+ RpcErrorCode2["CONNECTION_REFUSED"] = "CONNECTION_REFUSED";
6595
+ RpcErrorCode2["INVALID_NETWORK"] = "INVALID_NETWORK";
6596
+ RpcErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
6597
+ RpcErrorCode2["PARSE_ERROR"] = "PARSE_ERROR";
6598
+ RpcErrorCode2["INVALID_REQUEST"] = "INVALID_REQUEST";
6599
+ RpcErrorCode2["METHOD_NOT_FOUND"] = "METHOD_NOT_FOUND";
6600
+ RpcErrorCode2["INVALID_PARAMS"] = "INVALID_PARAMS";
6601
+ RpcErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
6602
+ RpcErrorCode2["TRANSACTION_REJECTED"] = "TRANSACTION_REJECTED";
6603
+ RpcErrorCode2["INSUFFICIENT_FUNDS"] = "INSUFFICIENT_FUNDS";
6604
+ RpcErrorCode2["TRANSACTION_CONFIRMATION_TIMEOUT"] = "TRANSACTION_CONFIRMATION_TIMEOUT";
6605
+ RpcErrorCode2["ACCOUNT_NOT_FOUND"] = "ACCOUNT_NOT_FOUND";
6606
+ RpcErrorCode2["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED";
6607
+ RpcErrorCode2["NODE_UNHEALTHY"] = "NODE_UNHEALTHY";
6608
+ return RpcErrorCode2;
6609
+ })(RpcErrorCode || {});
6610
+ var RpcError = class _RpcError extends Error {
6611
+ code;
6612
+ details;
6613
+ retryable;
6614
+ constructor(code, message, details = {}, retryable = false) {
6615
+ super(message);
6616
+ this.name = "RpcError";
6617
+ this.code = code;
6618
+ this.details = details;
6619
+ this.retryable = retryable;
6752
6620
  }
6753
- serializeCompactU16(buffer, value) {
6754
- if (value < 0 || value > 65535) {
6755
- throw new Error(`Value out of range for compact-u16: ${value}`);
6621
+ static requestTimeout(timeoutMs, details) {
6622
+ return new _RpcError(
6623
+ "REQUEST_TIMEOUT" /* REQUEST_TIMEOUT */,
6624
+ `RPC request timed out after ${timeoutMs}ms. The node may be slow or unreachable.`,
6625
+ { ...details, timeout: timeoutMs },
6626
+ true
6627
+ // Retryable
6628
+ );
6629
+ }
6630
+ static networkError(message, details) {
6631
+ return new _RpcError(
6632
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
6633
+ `Network error: ${message}. Check your internet connection and node URL.`,
6634
+ details,
6635
+ true
6636
+ // Retryable
6637
+ );
6638
+ }
6639
+ static invalidResponse(details) {
6640
+ return new _RpcError(
6641
+ "INVALID_RESPONSE" /* INVALID_RESPONSE */,
6642
+ "Received invalid response from RPC node. The response format is unexpected.",
6643
+ details,
6644
+ false
6645
+ );
6646
+ }
6647
+ static accountNotFound(pubkey) {
6648
+ return new _RpcError(
6649
+ "ACCOUNT_NOT_FOUND" /* ACCOUNT_NOT_FOUND */,
6650
+ `Account ${pubkey} not found on chain. It may not exist or has zero balance.`,
6651
+ { pubkey },
6652
+ false
6653
+ );
6654
+ }
6655
+ static rateLimitExceeded(details) {
6656
+ return new _RpcError(
6657
+ "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */,
6658
+ "Rate limit exceeded. Too many requests to the RPC endpoint. Try again later or use a different endpoint.",
6659
+ details,
6660
+ true
6661
+ // Can retry after delay
6662
+ );
6663
+ }
6664
+ static fromRpcCode(rpcCode, message, details) {
6665
+ const codeMap = {
6666
+ [-32700]: "PARSE_ERROR" /* PARSE_ERROR */,
6667
+ [-32600]: "INVALID_REQUEST" /* INVALID_REQUEST */,
6668
+ [-32601]: "METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
6669
+ [-32602]: "INVALID_PARAMS" /* INVALID_PARAMS */,
6670
+ [-32603]: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
6671
+ [429]: "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */
6672
+ };
6673
+ const code = codeMap[rpcCode] || "INTERNAL_ERROR" /* INTERNAL_ERROR */;
6674
+ const retryable = rpcCode === 429 || rpcCode === -32603;
6675
+ return new _RpcError(code, message, { ...details, rpcCode }, retryable);
6676
+ }
6677
+ toJSON() {
6678
+ return {
6679
+ code: this.code,
6680
+ message: this.message,
6681
+ details: this.details,
6682
+ retryable: this.retryable
6683
+ };
6684
+ }
6685
+ };
6686
+
6687
+ // src/rpc/clients/base-client.ts
6688
+ var BaseRpcClient = class {
6689
+ transport;
6690
+ requestId = 0;
6691
+ constructor(transport) {
6692
+ this.transport = transport;
6693
+ }
6694
+ /**
6695
+ * Makes a JSON-RPC 2.0 method call with type safety.
6696
+ *
6697
+ * Handles request serialization, response validation, and error mapping.
6698
+ */
6699
+ async call(method, params = []) {
6700
+ const requestId = this.nextRequestId();
6701
+ const request = {
6702
+ jsonrpc: "2.0",
6703
+ id: requestId,
6704
+ method,
6705
+ params
6706
+ };
6707
+ const requestBody = JSON.stringify(request);
6708
+ const requestDetails = { method, params, requestId };
6709
+ const data = await this.transport.request(requestBody, requestDetails);
6710
+ if (!this.isValidJsonRpcResponse(data)) {
6711
+ throw RpcError.invalidResponse({
6712
+ ...requestDetails,
6713
+ response: data
6714
+ });
6756
6715
  }
6757
- if (value <= 127) {
6758
- buffer.push(value);
6759
- return;
6716
+ const response = data;
6717
+ if (response.error) {
6718
+ throw RpcError.fromRpcCode(response.error.code, response.error.message, {
6719
+ ...requestDetails,
6720
+ rpcData: response.error.data
6721
+ });
6760
6722
  }
6761
- if (value <= 16383) {
6762
- buffer.push(value & 127 | 128);
6763
- buffer.push(value >> 7 & 127);
6764
- return;
6723
+ if (!("result" in response)) {
6724
+ throw RpcError.invalidResponse({
6725
+ ...requestDetails,
6726
+ response
6727
+ });
6765
6728
  }
6766
- buffer.push(value & 127 | 128);
6767
- buffer.push(value >> 7 & 127 | 128);
6768
- buffer.push(value >> 14 & 255);
6729
+ return response.result;
6769
6730
  }
6770
6731
  /**
6771
- * Get all signers required for this message.
6732
+ * Validate JSON-RPC response structure
6772
6733
  */
6773
- getSigners() {
6774
- return this.accountKeys.slice(0, this.header.numRequiredSignatures);
6734
+ isValidJsonRpcResponse(data) {
6735
+ if (typeof data !== "object" || data === null) {
6736
+ return false;
6737
+ }
6738
+ const response = data;
6739
+ return response.jsonrpc === "2.0" && typeof response.id === "number" && ("result" in response || "error" in response);
6775
6740
  }
6776
6741
  /**
6777
- * Check if a public key is a required signer.
6742
+ * Generates the next request ID with Overflow Protection.
6743
+ * @returns The next request ID.
6778
6744
  */
6779
- isSignerRequired(pubkey) {
6780
- return this.getSigners().some((signer) => signer.equals(pubkey));
6745
+ nextRequestId() {
6746
+ this.requestId = (this.requestId + 1) % Number.MAX_SAFE_INTEGER;
6747
+ return this.requestId;
6781
6748
  }
6782
6749
  /**
6783
- * Get the index of a signer in the signers array.
6784
- * Returns -1 if not a signer.
6750
+ * Returns the configured RPC endpoint URL.
6785
6751
  */
6786
- getSignerIndex(pubkey) {
6787
- return this.getSigners().findIndex((signer) => signer.equals(pubkey));
6752
+ getUrl() {
6753
+ return this.transport.getUrl();
6788
6754
  }
6789
6755
  };
6790
- function deserializeCompactU162(data, currentCursor) {
6791
- let cursor = currentCursor;
6792
- if (cursor >= data.length) {
6793
- throw new TransactionError(
6794
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6795
- "Insufficient data for compact-u16"
6796
- );
6797
- }
6798
- const firstByte = data[cursor++];
6799
- if ((firstByte & 128) === 0) {
6800
- return [firstByte, cursor];
6756
+
6757
+ // src/utils.ts
6758
+ function toBase64(bytes) {
6759
+ if (typeof btoa !== "undefined") {
6760
+ const chunkSize = 8192;
6761
+ let result = "";
6762
+ for (let i = 0; i < bytes.length; i += chunkSize) {
6763
+ const chunk = bytes.slice(i, i + chunkSize);
6764
+ result += String.fromCharCode(...chunk);
6765
+ }
6766
+ return btoa(result);
6801
6767
  }
6802
- if (cursor >= data.length) {
6803
- throw new TransactionError(
6804
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6805
- "Incomplete compact-u16 encoding"
6806
- );
6768
+ if (typeof Buffer !== "undefined") {
6769
+ return Buffer.from(bytes).toString("base64");
6807
6770
  }
6808
- const secondByte = data[cursor++];
6809
- if ((secondByte & 128) === 0) {
6810
- return [firstByte & 127 | secondByte << 7, cursor];
6771
+ throw new Error("No base64 encoding available in this environment");
6772
+ }
6773
+ function fromBase64(base64) {
6774
+ if (typeof atob !== "undefined") {
6775
+ const binary = atob(base64);
6776
+ const bytes = new Uint8Array(binary.length);
6777
+ for (let i = 0; i < binary.length; i++) {
6778
+ bytes[i] = binary.charCodeAt(i);
6779
+ }
6780
+ return bytes;
6811
6781
  }
6812
- if (cursor >= data.length) {
6813
- throw new TransactionError(
6814
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6815
- "Incomplete compact-u16 encoding"
6816
- );
6782
+ if (typeof Buffer !== "undefined") {
6783
+ return new Uint8Array(Buffer.from(base64, "base64"));
6817
6784
  }
6818
- const thirdByte = data[cursor++];
6819
- const value = firstByte & 127 | (secondByte & 127) << 7 | thirdByte << 14;
6820
- return [value, cursor];
6785
+ throw new Error("No base64 decoding available in this environment");
6786
+ }
6787
+ function sleep(ms) {
6788
+ return new Promise((resolve) => setTimeout(resolve, ms));
6789
+ }
6790
+ function calculateBackoff(attempt, baseMs = 1e3, maxMs = 3e4) {
6791
+ const exponentialDelay = baseMs * 2 ** attempt;
6792
+ const jitter = Math.random() * 0.3 * exponentialDelay;
6793
+ return Math.min(exponentialDelay + jitter, maxMs);
6794
+ }
6795
+ function getDevnetUrl() {
6796
+ return URL_DEVNET;
6797
+ }
6798
+ function getTestnetUrl() {
6799
+ return URL_TESTNET;
6800
+ }
6801
+ function getMainnetUrl() {
6802
+ return URL_MAINNET;
6803
+ }
6804
+ function getLocalnetUrl() {
6805
+ return URL_LOCALNET;
6821
6806
  }
6822
6807
 
6823
- // src/transaction/transaction.ts
6824
- var Transaction = class _Transaction {
6825
- /** The unsigned message */
6826
- message;
6827
- /** Signatures (64 bytes each), aligned with message.header.numRequiredSignatures */
6828
- signatures;
6829
- // Private constructor - use static factories
6830
- constructor(message, signatures) {
6831
- this.message = message;
6832
- this.signatures = signatures.map((sig) => new Uint8Array(sig));
6833
- if (signatures.length !== message.header.numRequiredSignatures) {
6834
- throw new TransactionError(
6835
- "INVALID_SIGNATURE" /* INVALID_SIGNATURE */,
6836
- `Signature count (${signatures.length}) doesn't match required signers (${message.header.numRequiredSignatures})`
6837
- );
6838
- }
6808
+ // src/rpc/clients/query-client.ts
6809
+ var QueryRpcClient = class extends BaseRpcClient {
6810
+ /**
6811
+ * Retrieve the balance of an account in kelvins (smallest unit).
6812
+ *
6813
+ * @param pubkey - The public key of the account to query
6814
+ * @returns The account balance in kelvins
6815
+ *
6816
+ * @example
6817
+ * ```typescript
6818
+ * const balance = await client.getBalance(publicKey);
6819
+ * console.log(`Balance: ${balance} kelvins`);
6820
+ * ```
6821
+ */
6822
+ async getBalance(pubkey) {
6823
+ const result = await this.call("getBalance", [
6824
+ { address: pubkey.toString() }
6825
+ ]);
6826
+ return BigInt(result.value);
6839
6827
  }
6840
6828
  /**
6841
- * Create an unsigned transaction from a message.
6842
- * All signature slots are initialized to zero.
6829
+ * Retrieve detailed information about an account.
6843
6830
  *
6844
- * @internal - Users should use TransactionBuilder instead
6831
+ * Returns account data including balance, owner program, stored data,
6832
+ * executable status, and rent epoch.
6833
+ *
6834
+ * @param pubkey - The public key of the account to query
6835
+ * @returns Account information, or null if the account does not exist
6836
+ *
6837
+ * @example
6838
+ * ```typescript
6839
+ * const info = await client.getAccountInfo(publicKey);
6840
+ * if (info) {
6841
+ * console.log(`Owner: ${info.owner}`);
6842
+ * console.log(`Balance: ${info.balance} kelvins`);
6843
+ * console.log(`Data length: ${info.data.length} bytes`);
6844
+ * }
6845
+ * ```
6845
6846
  */
6846
- static fromMessage(message) {
6847
- const numSignatures = message.header.numRequiredSignatures;
6848
- const signatures = Array.from(
6849
- { length: numSignatures },
6850
- () => new Uint8Array(SIGNATURE_LENGTH)
6851
- );
6852
- return new _Transaction(message, signatures);
6847
+ async getAccountInfo(pubkey) {
6848
+ const result = await this.call("getAccountInfo", [{ address: pubkey.toString(), encoding: "base64" }]);
6849
+ if (!result.value) {
6850
+ return null;
6851
+ }
6852
+ return {
6853
+ balance: BigInt(result.value.balance),
6854
+ owner: PublicKey.fromString(result.value.owner),
6855
+ data: fromBase64(result.value.data),
6856
+ executable: result.value.executable,
6857
+ rentEpoch: BigInt(result.value.rentEpoch)
6858
+ };
6853
6859
  }
6854
6860
  /**
6855
- * Create transaction from message and existing signatures.
6856
- * @internal
6861
+ * Retrieve the current block height of the blockchain.
6862
+ *
6863
+ * The block height represents the number of blocks that have been
6864
+ * confirmed on the chain since genesis.
6865
+ *
6866
+ * @returns The current block height
6867
+ *
6868
+ * @example
6869
+ * ```typescript
6870
+ * const height = await client.getBlockHeight();
6871
+ * console.log(`Current block height: ${height}`);
6872
+ * ```
6857
6873
  */
6858
- static fromMessageAndSignatures(message, signatures) {
6859
- return new _Transaction(message, signatures);
6874
+ async getBlockHeight() {
6875
+ const result = await this.call("getBlockHeight", []);
6876
+ return BigInt(result);
6860
6877
  }
6861
6878
  /**
6862
- * Deserialize a transaction from wire format.
6879
+ * Retrieve detailed information about a confirmed transaction.
6880
+ *
6881
+ * Returns transaction metadata including the block height it was
6882
+ * confirmed in and any execution errors.
6883
+ *
6884
+ * @param signature - The transaction signature to query
6885
+ * @returns Transaction information, or null if the transaction is not found
6886
+ *
6887
+ * @example
6888
+ * ```typescript
6889
+ * const tx = await client.getTransaction(signature);
6890
+ * if (tx) {
6891
+ * console.log(`Confirmed in block: ${tx.blockHeight}`);
6892
+ * if (tx.err) {
6893
+ * console.log(`Transaction failed: ${tx.err}`);
6894
+ * }
6895
+ * }
6896
+ * ```
6863
6897
  */
6864
- static deserialize(data) {
6865
- if (data.length === 0) {
6866
- throw new TransactionError(
6867
- "SERIALIZATION_FAILED" /* SERIALIZATION_FAILED */,
6868
- "Cannot deserialize empty transaction data"
6869
- );
6870
- }
6871
- let cursor = 0;
6872
- const [signaturesLength, newCursor] = deserializeCompactU16(data, cursor);
6873
- cursor = newCursor;
6874
- const signatures = [];
6875
- for (let i = 0; i < signaturesLength; i++) {
6876
- if (data.length < cursor + SIGNATURE_LENGTH) {
6877
- throw new TransactionError(
6878
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6879
- `Insufficient data for signature ${i}: need ${SIGNATURE_LENGTH} bytes at offset ${cursor}`
6880
- );
6881
- }
6882
- const signature = data.slice(cursor, cursor + SIGNATURE_LENGTH);
6883
- signatures.push(signature);
6884
- cursor += SIGNATURE_LENGTH;
6885
- }
6886
- if (cursor >= data.length) {
6887
- throw new TransactionError(
6888
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6889
- "No message data found after signatures"
6890
- );
6898
+ async getTransaction(signature) {
6899
+ const result = await this.call("getTransaction", [signature]);
6900
+ if (!result) {
6901
+ return null;
6891
6902
  }
6892
- const messageBytes = data.slice(cursor);
6893
- const message = Message.deserialize(messageBytes);
6894
- return new _Transaction(message, signatures);
6903
+ return {
6904
+ signature,
6905
+ blockHeight: BigInt(result.block_height ?? 0),
6906
+ err: result.err ?? result.meta?.err ?? void 0
6907
+ };
6895
6908
  }
6896
- getMessage() {
6897
- return this.message;
6909
+ /**
6910
+ * Retrieve the total number of transactions processed since genesis.
6911
+ *
6912
+ * @returns The total transaction count
6913
+ *
6914
+ * @example
6915
+ * ```typescript
6916
+ * const count = await client.getTransactionCount();
6917
+ * console.log(`Total transactions: ${count}`);
6918
+ * ```
6919
+ */
6920
+ async getTransactionCount() {
6921
+ const result = await this.call("getTransactionCount", []);
6922
+ return BigInt(result);
6898
6923
  }
6899
6924
  /**
6900
- * Sign the transaction with a keypair.
6901
- * Returns a NEW Transaction instance.
6925
+ * Retrieve the status of multiple transaction signatures in a single request.
6902
6926
  *
6903
- * @param keypair - Keypair to sign with
6904
- * @returns New Transaction instance with signature added
6927
+ * Useful for batch-checking transaction confirmations. Returns null for
6928
+ * signatures that are not found or have expired from the status cache.
6929
+ *
6930
+ * @param signatures - Array of transaction signatures to query
6931
+ * @returns Array of signature statuses (null if signature not found)
6905
6932
  *
6906
6933
  * @example
6907
6934
  * ```typescript
6908
- * const signedTx = tx.sign(keypair);
6909
- * await client.sendTransaction(signedTx.serialize());
6935
+ * const statuses = await client.getSignatureStatuses([sig1, sig2, sig3]);
6936
+ * statuses.forEach((status, i) => {
6937
+ * if (status) {
6938
+ * console.log(`${signatures[i]}: slot ${status.slot}, executed: ${status.executed}`);
6939
+ * } else {
6940
+ * console.log(`${signatures[i]}: not found`);
6941
+ * }
6942
+ * });
6910
6943
  * ```
6911
6944
  */
6912
- sign(keypair) {
6913
- const messageBytes = this.message.serialize();
6914
- const signature = keypair.sign(messageBytes);
6915
- return this.addSignatureForPubkey(keypair.publicKey, signature);
6945
+ async getSignatureStatuses(signatures) {
6946
+ const result = await this.call("getSignatureStatuses", [signatures]);
6947
+ return result.value.map((status) => {
6948
+ if (!status) {
6949
+ return null;
6950
+ }
6951
+ return {
6952
+ slot: BigInt(status.slot),
6953
+ executed: status.executed,
6954
+ err: status.err
6955
+ };
6956
+ });
6957
+ }
6958
+ /**
6959
+ * Retrieve information about the current epoch.
6960
+ *
6961
+ * Returns epoch metadata including the current epoch number, slot position
6962
+ * within the epoch, total slots per epoch, and current block height.
6963
+ *
6964
+ * @returns Current epoch information
6965
+ *
6966
+ * @example
6967
+ * ```typescript
6968
+ * const info = await client.getEpochInfo();
6969
+ * console.log(`Epoch: ${info.epoch}`);
6970
+ * console.log(`Slot ${info.slotIndex} of ${info.slotsInEpoch}`);
6971
+ * console.log(`Block height: ${info.blockHeight}`);
6972
+ * ```
6973
+ */
6974
+ async getEpochInfo() {
6975
+ const result = await this.call("getEpochInfo", []);
6976
+ return {
6977
+ epoch: BigInt(result.epoch),
6978
+ slotIndex: BigInt(result.slotIndex),
6979
+ slotsInEpoch: BigInt(result.slotsInEpoch),
6980
+ absoluteSlot: BigInt(result.absoluteSlot),
6981
+ blockHeight: BigInt(result.blockHeight),
6982
+ transactionCount: result.transactionCount ? BigInt(result.transactionCount) : void 0
6983
+ };
6916
6984
  }
6917
6985
  /**
6918
- * Sign with multiple keypairs at once.
6919
- * Returns a NEW Transaction instance.
6986
+ * Check the health status of the RPC node.
6987
+ *
6988
+ * Returns "ok" if the node is healthy. If the node is unhealthy,
6989
+ * returns an error message describing the issue.
6990
+ *
6991
+ * @returns "ok" if healthy, otherwise an error message
6920
6992
  *
6921
6993
  * @example
6922
6994
  * ```typescript
6923
- * const signed = tx.signAll([keypair1, keypair2, keypair3]);
6995
+ * const health = await client.getHealth();
6996
+ * if (health === "ok") {
6997
+ * console.log("Node is healthy");
6998
+ * } else {
6999
+ * console.log(`Node unhealthy: ${health}`);
7000
+ * }
6924
7001
  * ```
6925
7002
  */
6926
- signAll(keypairs) {
6927
- let result = this;
6928
- for (const keypair of keypairs) {
6929
- result = result.sign(keypair);
6930
- }
7003
+ async getHealth() {
7004
+ const result = await this.call("getHealth", []);
6931
7005
  return result;
6932
7006
  }
7007
+ };
7008
+
7009
+ // src/rpc/clients/transaction-client.ts
7010
+ var DEFAULT_MAX_RETRIES = 10;
7011
+ var DEFAULT_RETRY_DELAY_MS = 200;
7012
+ var TransactionRpcClient = class extends BaseRpcClient {
6933
7013
  /**
6934
- * Sign the transaction with a Signer interface (async).
6935
- * Returns a NEW Transaction instance.
7014
+ * Submit a signed transaction to the blockchain.
7015
+ *
7016
+ * Sends the transaction to the network for processing. The transaction
7017
+ * must be fully signed before submission. Returns immediately with the
7018
+ * transaction signature - use {@link confirmTransaction} or
7019
+ * {@link sendAndConfirmTransaction} to wait for confirmation.
7020
+ *
7021
+ * @param transaction - Serialized signed transaction bytes
7022
+ * @param options - Transaction submission options
7023
+ * @returns Transaction signature (base58 encoded)
6936
7024
  *
6937
7025
  * @example
6938
7026
  * ```typescript
6939
- * const signedTx = await tx.signWith(browserWallet);
7027
+ * const signature = await client.sendTransaction(signedTx);
7028
+ * console.log(`Submitted: ${signature}`);
7029
+ *
7030
+ * // With options
7031
+ * const signature = await client.sendTransaction(signedTx, {
7032
+ * skipPreflight: true,
7033
+ * maxRetries: 3,
7034
+ * });
6940
7035
  * ```
6941
7036
  */
6942
- async signWith(signer) {
6943
- const pubkey = await signer.getPublicKey();
6944
- const messageBytes = this.message.serialize();
6945
- const signature = await signer.signMessage(messageBytes);
6946
- return this.addSignatureForPubkey(pubkey, signature);
7037
+ async sendTransaction(transaction, options) {
7038
+ const base64Tx = toBase64(transaction);
7039
+ const config = {
7040
+ encoding: "base64",
7041
+ skipPreflight: options?.skipPreflight ?? false,
7042
+ maxRetries: options?.maxRetries ?? 5
7043
+ };
7044
+ const signature = await this.call("sendTransaction", [
7045
+ base64Tx,
7046
+ config
7047
+ ]);
7048
+ return signature;
6947
7049
  }
6948
7050
  /**
6949
- * Sign with multiple signers.
6950
- * Returns a NEW Transaction instance.
7051
+ * Wait for a transaction to be confirmed.
7052
+ *
7053
+ * A transaction is considered confirmed when:
7054
+ * - It has been processed in a block (`blockHeight > 0`)
7055
+ *
7056
+ * @param signature - Transaction signature to monitor
7057
+ * @param options - Confirmation options
7058
+ * @returns Confirmed transaction details
7059
+ * @throws {TransactionFailedError} If the transaction fails on-chain
7060
+ * @throws {TransactionConfirmationTimeoutError} If confirmation times out
6951
7061
  */
6952
- async signAllWith(signers) {
6953
- let result = this;
6954
- for (const signer of signers) {
6955
- result = await result.signWith(signer);
7062
+ async confirmTransaction(signature, options) {
7063
+ const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
7064
+ const retryDelay = options?.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
7065
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
7066
+ if (attempt > 0) {
7067
+ await this.sleep(retryDelay);
7068
+ }
7069
+ try {
7070
+ const txInfo = await this.getTransaction(signature);
7071
+ if (!txInfo) {
7072
+ continue;
7073
+ }
7074
+ if (txInfo.err) {
7075
+ return {
7076
+ signature,
7077
+ executed: false,
7078
+ err: txInfo.err
7079
+ };
7080
+ }
7081
+ if (txInfo.blockHeight && txInfo.blockHeight > 0n) {
7082
+ return {
7083
+ signature,
7084
+ executed: true,
7085
+ err: void 0
7086
+ };
7087
+ }
7088
+ } catch (error) {
7089
+ if (error instanceof RpcError && error.code === "TRANSACTION_REJECTED" /* TRANSACTION_REJECTED */) {
7090
+ throw error;
7091
+ }
7092
+ }
6956
7093
  }
6957
- return result;
7094
+ throw new RpcError(
7095
+ "TRANSACTION_CONFIRMATION_TIMEOUT" /* TRANSACTION_CONFIRMATION_TIMEOUT */,
7096
+ "Transaction confirmation timed out",
7097
+ {
7098
+ signature,
7099
+ maxRetries
7100
+ }
7101
+ );
6958
7102
  }
6959
7103
  /**
6960
- * Partially sign the transaction (for multi-sig transactions).
6961
- * Returns a NEW Transaction instance.
7104
+ * Submit a signed transaction and wait for confirmation.
7105
+ *
7106
+ * Polls the transaction status until it is confirmed (blockHeight > 0),
7107
+ * or until the maximum number of retries is reached.
7108
+ *
7109
+ * @param transaction - Serialized signed transaction bytes
7110
+ * @param options - Transaction submission and confirmation options
7111
+ * @returns Confirmed transaction details
7112
+ * @throws {TransactionFailedError} If the transaction fails on-chain
7113
+ * @throws {TransactionConfirmationTimeoutError} If confirmation times out
6962
7114
  *
6963
7115
  * @example
6964
7116
  * ```typescript
6965
- * const signedTx = tx
6966
- * .partialSign(signer1)
6967
- * .partialSign(signer2);
7117
+ * const result = await client.sendAndConfirmTransaction(signedTx);
7118
+ * console.log(`Confirmed in block ${result.blockHeight}, executed: ${result.executed}`);
7119
+ *
7120
+ * // With custom retry settings
7121
+ * const result = await client.sendAndConfirmTransaction(signedTx, {
7122
+ * maxRetries: 3,
7123
+ * retryDelay: 500,
7124
+ * });
6968
7125
  * ```
6969
7126
  */
6970
- partialSign(keypair) {
6971
- return this.sign(keypair);
6972
- }
6973
- /**
6974
- * Partially sign with a Signer interface (async).
6975
- * Returns a NEW Transaction instance.
6976
- */
6977
- async partialSignWith(signer) {
6978
- return this.signWith(signer);
7127
+ async sendAndConfirmTransaction(transaction, options) {
7128
+ const signature = await this.sendTransaction(transaction, options);
7129
+ return await this.confirmTransaction(signature, options);
6979
7130
  }
6980
7131
  /**
6981
- * Add a signature at a specific index.
6982
- * Returns a NEW Transaction instance.
7132
+ * Request an airdrop of tokens to an account.
6983
7133
  *
6984
- * Most users should use sign() or signAll() instead.
7134
+ * **Note**: Only available on devnet and testnet networks.
7135
+ *
7136
+ * Returns immediately with the airdrop transaction signature.
7137
+ * Use {@link requestAirdropAndConfirm} to wait for the airdrop to complete.
7138
+ *
7139
+ * @param pubkey - The public key of the account to receive tokens
7140
+ * @param amount - Amount to airdrop in kelvins (smallest unit)
7141
+ * @returns Airdrop transaction signature
7142
+ *
7143
+ * @example
7144
+ * ```typescript
7145
+ * const signature = await client.requestAirdrop(publicKey, 1_000_000_000n);
7146
+ * console.log(`Airdrop requested: ${signature}`);
7147
+ * ```
6985
7148
  */
6986
- addSignature(index, signature) {
6987
- if (index < 0 || index >= this.signatures.length) {
6988
- throw new TransactionError(
6989
- "SIGNATURE_OUT_OF_BOUNDS" /* SIGNATURE_OUT_OF_BOUNDS */,
6990
- `Signature index ${index} out of bounds (must be 0-${this.signatures.length - 1})`
6991
- );
6992
- }
6993
- const sigBytes = signature instanceof Uint8Array ? signature : signature.toBytes();
6994
- if (sigBytes.length !== SIGNATURE_LENGTH) {
6995
- throw new TransactionError(
6996
- "INVALID_SIGNATURE" /* INVALID_SIGNATURE */,
6997
- `Signature must be ${SIGNATURE_LENGTH} bytes, got ${sigBytes.length}`
7149
+ async requestAirdrop(pubkey, amount) {
7150
+ if (amount > BigInt(Number.MAX_SAFE_INTEGER)) {
7151
+ throw new RpcError(
7152
+ "INVALID_PARAMS" /* INVALID_PARAMS */,
7153
+ `Airdrop amount ${amount} exceeds maximum safe value`
6998
7154
  );
6999
7155
  }
7000
- const newSignatures = this.signatures.map(
7001
- (sig, i) => i === index ? new Uint8Array(sigBytes) : new Uint8Array(sig)
7002
- );
7003
- return new _Transaction(this.message, newSignatures);
7156
+ const signature = await this.call("requestAirdrop", [
7157
+ pubkey.toString(),
7158
+ Number(amount)
7159
+ ]);
7160
+ return signature;
7004
7161
  }
7005
7162
  /**
7006
- * Add a signature for a specific public key.
7007
- * Returns a NEW Transaction instance.
7163
+ * Request an airdrop of tokens and wait for confirmation.
7008
7164
  *
7009
- * Most users should use sign() or signAll() instead.
7165
+ * **Note**: Only available on devnet and testnet networks.
7166
+ *
7167
+ * Combines {@link requestAirdrop} and {@link confirmTransaction} into
7168
+ * a single call for convenience.
7169
+ *
7170
+ * @param pubkey - The public key of the account to receive tokens
7171
+ * @param amount - Amount to airdrop in kelvins (smallest unit)
7172
+ * @param options - Confirmation options (max retries, retry delay)
7173
+ * @returns Confirmed transaction details
7174
+ * @throws {RpcError} If the airdrop transaction fails or confirmation times out
7175
+ *
7176
+ * @example
7177
+ * ```typescript
7178
+ * const result = await client.requestAirdropAndConfirm(publicKey, 1_000_000_000n);
7179
+ * if (result.executed) {
7180
+ * console.log("Airdrop confirmed!");
7181
+ * }
7182
+ * ```
7010
7183
  */
7011
- addSignatureForPubkey(pubkey, signature) {
7012
- const signerIndex = this.message.getSignerIndex(pubkey);
7013
- if (signerIndex === -1) {
7014
- throw TransactionError.signerNotFound(pubkey.toString());
7184
+ async requestAirdropAndConfirm(pubkey, amount, options) {
7185
+ const signature = await this.requestAirdrop(pubkey, amount);
7186
+ return await this.confirmTransaction(signature, options);
7187
+ }
7188
+ async getTransaction(signature) {
7189
+ const result = await this.call("getTransaction", [signature]);
7190
+ if (!result) {
7191
+ return null;
7015
7192
  }
7016
- return this.addSignature(signerIndex, signature);
7193
+ return {
7194
+ signature,
7195
+ blockHeight: BigInt(result.block_height ?? 0),
7196
+ err: result.err ?? result.meta?.err ?? void 0
7197
+ };
7017
7198
  }
7018
7199
  /**
7019
- * Check if transaction is fully signed (all signatures present).
7200
+ * Sleeps for a given number of milliseconds.
7201
+ * @param ms - The number of milliseconds to sleep.
7202
+ * @returns A promise that resolves when the sleep is complete.
7020
7203
  */
7021
- isSigned() {
7022
- return this.signatures.every((sig) => sig.some((byte) => byte !== 0));
7204
+ sleep(ms) {
7205
+ return new Promise((resolve) => setTimeout(resolve, ms));
7206
+ }
7207
+ };
7208
+
7209
+ // src/rpc/clients/client.ts
7210
+ var RialoClient = class {
7211
+ queryClient;
7212
+ transactionClient;
7213
+ transport;
7214
+ chain;
7215
+ constructor(transport, chain2) {
7216
+ this.chain = chain2;
7217
+ this.transport = transport;
7218
+ this.queryClient = new QueryRpcClient(transport);
7219
+ this.transactionClient = new TransactionRpcClient(transport);
7023
7220
  }
7024
7221
  /**
7025
- * Check if a specific signature slot is filled.
7222
+ * Returns the configured RPC endpoint URL.
7026
7223
  */
7027
- isSignaturePresent(index) {
7028
- if (index < 0 || index >= this.signatures.length) {
7029
- return false;
7030
- }
7031
- return this.signatures[index].some((byte) => byte !== 0);
7224
+ getUrl() {
7225
+ return this.transport.getUrl();
7032
7226
  }
7033
7227
  /**
7034
- * Get all signatures (returns copies to prevent mutation).
7228
+ * Returns the chain identifier.
7035
7229
  */
7036
- getSignatures() {
7037
- return this.signatures.map((sig) => new Uint8Array(sig));
7230
+ getChainIdentifier() {
7231
+ return this.chain.id;
7038
7232
  }
7039
7233
  /**
7040
- * Get a specific signature (returns copy).
7234
+ * Returns the chain configuration.
7041
7235
  */
7042
- getSignature(index) {
7043
- if (index < 0 || index >= this.signatures.length) {
7044
- throw new TransactionError(
7045
- "SIGNATURE_OUT_OF_BOUNDS" /* SIGNATURE_OUT_OF_BOUNDS */,
7046
- `Signature index ${index} out of bounds`
7047
- );
7048
- }
7049
- return new Uint8Array(this.signatures[index]);
7236
+ getChainConfig() {
7237
+ return this.chain;
7050
7238
  }
7051
7239
  /**
7052
- * Get a specific signature for a public key.
7240
+ * Retrieves the balance of an account in kelvins (smallest unit).
7053
7241
  */
7054
- getSignatureForPubkey(pubkey) {
7055
- const signerIndex = this.message.getSignerIndex(pubkey);
7056
- if (signerIndex === -1) {
7057
- throw TransactionError.signerNotFound(pubkey.toString());
7058
- }
7059
- return this.getSignature(signerIndex);
7242
+ async getBalance(pubkey) {
7243
+ return await this.queryClient.getBalance(pubkey);
7060
7244
  }
7061
7245
  /**
7062
- * Get required signers for this transaction.
7246
+ * Retrieves detailed information about an account.
7247
+ *
7248
+ * @returns Account info or null if account doesn't exist
7063
7249
  */
7064
- getSigners() {
7065
- return this.message.getSigners();
7250
+ async getAccountInfo(pubkey) {
7251
+ return await this.queryClient.getAccountInfo(pubkey);
7066
7252
  }
7067
7253
  /**
7068
- * Get the number of required signatures.
7254
+ * Retrieves the current block height.
7069
7255
  */
7070
- getRequiredSignatureCount() {
7071
- return this.message.header.numRequiredSignatures;
7256
+ async getBlockHeight() {
7257
+ return await this.queryClient.getBlockHeight();
7072
7258
  }
7073
7259
  /**
7074
- * Throw an error if the transaction is not fully signed.
7075
- *
7076
- * @throws {TransactionError} If transaction is not fully signed
7260
+ * Retrieves detailed information about a transaction.
7077
7261
  *
7078
- * @example
7079
- * ```typescript
7080
- * signedTx.ensureSigned(); // Throws if not signed
7081
- * await client.sendTransaction(signedTx.serialize());
7082
- * ```
7262
+ * @returns Transaction info or null if transaction not found
7083
7263
  */
7084
- ensureSigned() {
7085
- if (!this.isSigned()) {
7086
- const missingIndices = this.signatures.map((sig, i) => ({ sig, i })).filter(({ sig }) => !sig.some((byte) => byte !== 0)).map(({ i }) => i);
7087
- const signers = this.getSigners();
7088
- const missingSigners = missingIndices.map((i) => signers[i].toString());
7089
- throw new TransactionError(
7090
- "MISSING_SIGNATURE" /* MISSING_SIGNATURE */,
7091
- `Transaction is not fully signed. Missing signatures for: ${missingSigners.join(", ")}`,
7092
- { missingIndices, missingSigners }
7093
- );
7094
- }
7264
+ async getTransaction(signature) {
7265
+ return await this.queryClient.getTransaction(signature);
7095
7266
  }
7096
7267
  /**
7097
- * Serialize transaction to wire format.
7268
+ * Retrieves the total number of transactions processed since genesis.
7098
7269
  */
7099
- serialize() {
7100
- const compactU16Size = this.signatures.length < 128 ? 1 : 2;
7101
- const sigsSize = compactU16Size + this.signatures.length * SIGNATURE_LENGTH;
7102
- const messageBytes = this.message.serialize();
7103
- const totalSize = sigsSize + messageBytes.length;
7104
- const buffer = new Uint8Array(totalSize);
7105
- let offset = 0;
7106
- offset = writeCompactU16(buffer, offset, this.signatures.length);
7107
- for (const sig of this.signatures) {
7108
- buffer.set(sig, offset);
7109
- offset += SIGNATURE_LENGTH;
7110
- }
7111
- buffer.set(messageBytes, offset);
7112
- return buffer;
7270
+ async getTransactionCount() {
7271
+ return await this.queryClient.getTransactionCount();
7113
7272
  }
7114
- };
7115
-
7116
- // src/transaction/transaction-builder.ts
7117
- var TransactionBuilder = class _TransactionBuilder {
7118
- payer;
7119
- recentBlockhash;
7120
- txCreationTime;
7121
- instructions = [];
7122
- constructor() {
7273
+ /**
7274
+ * Retrieves the status of multiple transaction signatures.
7275
+ */
7276
+ async getSignatureStatuses(signatures) {
7277
+ return await this.queryClient.getSignatureStatuses(signatures);
7123
7278
  }
7124
7279
  /**
7125
- * Create a new transaction builder.
7280
+ * Retrieves current epoch information.
7126
7281
  */
7127
- static create() {
7128
- return new _TransactionBuilder();
7282
+ async getEpochInfo() {
7283
+ return await this.queryClient.getEpochInfo();
7129
7284
  }
7130
7285
  /**
7131
- * Set the fee payer for this transaction.
7286
+ * Checks the health status of the RPC node.
7132
7287
  *
7133
- * The payer will be the first account and must sign the transaction.
7134
- * The payer pays for transaction fees.
7288
+ * @returns "ok" if healthy, error message otherwise
7289
+ */
7290
+ async getHealth() {
7291
+ return await this.queryClient.getHealth();
7292
+ }
7293
+ /**
7294
+ * Submits a signed transaction to the blockchain.
7135
7295
  *
7136
- * @param payer - Public key of the fee payer
7296
+ * @param transaction - Serialized signed transaction bytes
7297
+ * @param options - Transaction submission options
7298
+ * @returns Transaction signature
7137
7299
  */
7138
- setPayer(payer) {
7139
- this.payer = payer;
7140
- return this;
7300
+ async sendTransaction(transaction, options) {
7301
+ return await this.transactionClient.sendTransaction(transaction, options);
7141
7302
  }
7142
7303
  /**
7143
- * Set the recent blockhash for replay protection.
7304
+ * Requests an airdrop of tokens to an account.
7144
7305
  *
7145
- * Get this from client.getLatestBlockhash().
7146
- * Transactions are only valid for ~60 seconds after the blockhash.
7306
+ * **Note**: Only available on devnet and testnet.
7147
7307
  *
7148
- * @param blockhash - Recent blockhash from the network
7308
+ * @param pubkey - Account to receive the airdrop
7309
+ * @param amount - Amount in kelvins (smallest unit)
7310
+ * @returns Transaction signature
7149
7311
  */
7150
- setRecentBlockhash(blockhash) {
7151
- this.recentBlockhash = blockhash;
7152
- return this;
7312
+ async requestAirdrop(pubkey, amount) {
7313
+ return await this.transactionClient.requestAirdrop(pubkey, amount);
7153
7314
  }
7154
7315
  /**
7155
- * Set the transaction creation timestamp.
7316
+ * Submits a signed transaction and waits for confirmation.
7156
7317
  *
7157
- * This is the time the transaction was created, in milliseconds since Unix epoch.
7158
- * It can be used for additional replay protection or auditing.
7318
+ * @param transaction - Serialized signed transaction bytes
7319
+ * @param options - Transaction submission and confirmation options
7320
+ * @returns Confirmed transaction details
7321
+ * @throws {TransactionFailedError} If the transaction fails on-chain
7322
+ * @throws {TransactionConfirmationTimeoutError} If confirmation times out
7159
7323
  *
7160
- * @param txCreationTime - Transaction creation time in milliseconds since Unix epoch
7324
+ * @example
7325
+ * ```typescript
7326
+ * const result = await client.sendAndConfirmTransaction(signedTx);
7327
+ * console.log(`Confirmed in slot ${result.slot}`);
7328
+ * ```
7161
7329
  */
7162
- setTxCreationTime(txCreationTime) {
7163
- this.txCreationTime = txCreationTime;
7164
- return this;
7330
+ async sendAndConfirmTransaction(transaction, options) {
7331
+ return await this.transactionClient.sendAndConfirmTransaction(
7332
+ transaction,
7333
+ options
7334
+ );
7165
7335
  }
7166
7336
  /**
7167
- * Add an instruction to the transaction.
7337
+ * Waits for a transaction to be confirmed.
7168
7338
  *
7169
- * @param instruction - Instruction to add
7339
+ * @param signature - Transaction signature to monitor
7340
+ * @param options - Confirmation options
7341
+ * @returns Confirmed transaction details
7170
7342
  */
7171
- addInstruction(instruction) {
7172
- this.instructions.push(instruction);
7173
- return this;
7343
+ async confirmTransaction(signature, options) {
7344
+ return await this.transactionClient.confirmTransaction(signature, options);
7174
7345
  }
7175
7346
  /**
7176
- * Add multiple instructions at once.
7347
+ * Requests an airdrop and waits for confirmation.
7177
7348
  *
7178
- * @param instructions - Array of instructions to add
7349
+ * **Note**: Only available on devnet and testnet.
7179
7350
  */
7180
- addInstructions(instructions) {
7181
- this.instructions.push(...instructions);
7182
- return this;
7351
+ async requestAirdropAndConfirm(pubkey, amount, options) {
7352
+ return await this.transactionClient.requestAirdropAndConfirm(
7353
+ pubkey,
7354
+ amount,
7355
+ options
7356
+ );
7357
+ }
7358
+ };
7359
+
7360
+ // src/rpc/http-transport.ts
7361
+ var DEFAULT_CONFIG = {
7362
+ timeout: 3e4,
7363
+ // 30 seconds
7364
+ maxRetries: 3,
7365
+ retryBaseDelay: 1e3,
7366
+ // 1 second
7367
+ retryMaxDelay: 3e4,
7368
+ // 30 seconds
7369
+ headers: {}
7370
+ };
7371
+ var HttpTransport = class {
7372
+ url;
7373
+ config;
7374
+ constructor(url, config = {}) {
7375
+ this.url = url;
7376
+ this.config = { ...DEFAULT_CONFIG, ...config };
7183
7377
  }
7184
7378
  /**
7185
- * Build the transaction (unsigned).
7186
- *
7187
- * Returns an unsigned Transaction that's ready to be signed.
7188
- *
7189
- * @returns Unsigned Transaction
7190
- * @throws {TransactionError} If payer, blockhash, or instructions are missing
7379
+ * Makes an HTTP request with automatic retry logic.
7191
7380
  *
7192
- * @example
7193
- * ```typescript
7194
- * const tx = builder.build();
7195
- * const signedTx = tx.sign(keypair);
7196
- * ```
7381
+ * Retries are attempted for network errors and server errors (5xx).
7382
+ * Uses exponential backoff between retry attempts.
7197
7383
  */
7198
- build() {
7199
- if (!this.payer) {
7200
- throw new TransactionError(
7201
- "INVALID_ACCOUNT_META" /* INVALID_ACCOUNT_META */,
7202
- "Transaction must have a fee payer. Use setPayer() to set the fee payer."
7203
- );
7384
+ async request(body, requestDetails = {}) {
7385
+ let lastError;
7386
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
7387
+ try {
7388
+ return await this.makeRequest(body, requestDetails, attempt);
7389
+ } catch (error) {
7390
+ lastError = error;
7391
+ if (error instanceof RpcError && !error.retryable) {
7392
+ throw error;
7393
+ }
7394
+ if (attempt === this.config.maxRetries) {
7395
+ throw error;
7396
+ }
7397
+ const delay = calculateBackoff(
7398
+ attempt,
7399
+ this.config.retryBaseDelay,
7400
+ this.config.retryMaxDelay
7401
+ );
7402
+ await sleep(delay);
7403
+ }
7204
7404
  }
7205
- if (!this.recentBlockhash) {
7206
- throw new TransactionError(
7207
- "INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
7208
- "Transaction must have a recent blockhash. Use setRecentBlockhash() to set the blockhash."
7209
- );
7405
+ throw lastError;
7406
+ }
7407
+ /**
7408
+ * Make a single HTTP request with timeout
7409
+ */
7410
+ async makeRequest(body, requestDetails, attempt) {
7411
+ const controller = new AbortController();
7412
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
7413
+ try {
7414
+ const options = {
7415
+ method: "POST",
7416
+ headers: {
7417
+ "Content-Type": "application/json",
7418
+ ...this.config.headers
7419
+ },
7420
+ body,
7421
+ signal: controller.signal
7422
+ };
7423
+ const response = await fetch(this.url, options);
7424
+ if (!response.ok) {
7425
+ throw await this.handleHttpError(response, requestDetails, attempt);
7426
+ }
7427
+ const data = await response.json();
7428
+ return data;
7429
+ } catch (error) {
7430
+ if (error instanceof Error && error.name === "AbortError") {
7431
+ throw RpcError.requestTimeout(this.config.timeout, {
7432
+ ...requestDetails,
7433
+ url: this.url,
7434
+ attempts: attempt + 1
7435
+ });
7436
+ }
7437
+ if (error instanceof TypeError) {
7438
+ throw RpcError.networkError(error.message, {
7439
+ ...requestDetails,
7440
+ url: this.url,
7441
+ attempts: attempt + 1,
7442
+ cause: error.message
7443
+ });
7444
+ }
7445
+ if (error instanceof RpcError) {
7446
+ throw error;
7447
+ }
7448
+ throw RpcError.networkError("Unknown network error", {
7449
+ ...requestDetails,
7450
+ url: this.url,
7451
+ attempts: attempt + 1,
7452
+ cause: error instanceof Error ? error.message : String(error)
7453
+ });
7454
+ } finally {
7455
+ clearTimeout(timeoutId);
7210
7456
  }
7211
- if (!this.txCreationTime) {
7212
- throw new TransactionError(
7213
- "INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
7214
- "Transaction must have a creation timestamp. Use setTxCreationTime() to set the creation time."
7215
- );
7457
+ }
7458
+ /**
7459
+ * Handle HTTP error responses.
7460
+ *
7461
+ * Parses the response body to extract JSON-RPC error details when available,
7462
+ * regardless of HTTP status code. Falls back to HTTP status-based error handling.
7463
+ */
7464
+ async handleHttpError(response, requestDetails, attempt) {
7465
+ const status = response.status;
7466
+ const isRetryable = status >= 500 || status === 429;
7467
+ const baseDetails = {
7468
+ ...requestDetails,
7469
+ httpStatus: status,
7470
+ url: this.url,
7471
+ attempts: attempt + 1
7472
+ };
7473
+ const { message, rpcCode, errorData } = await this.parseErrorResponse(
7474
+ response,
7475
+ status
7476
+ );
7477
+ if (status === 429) {
7478
+ return RpcError.rateLimitExceeded({
7479
+ ...baseDetails,
7480
+ serverError: errorData
7481
+ });
7216
7482
  }
7217
- if (this.instructions.length === 0) {
7218
- throw TransactionError.noInstructions();
7483
+ if (rpcCode !== void 0) {
7484
+ return RpcError.fromRpcCode(rpcCode, message, {
7485
+ ...baseDetails,
7486
+ serverError: errorData
7487
+ });
7219
7488
  }
7220
- const accountTable = new AccountMetaTable();
7221
- accountTable.add({
7222
- pubkey: this.payer,
7223
- isSigner: true,
7224
- isWritable: true
7225
- });
7226
- for (const instruction of this.instructions) {
7227
- accountTable.addAll(instruction.accounts);
7228
- accountTable.add({
7229
- pubkey: instruction.programId,
7230
- isSigner: false,
7231
- isWritable: false
7489
+ if (status >= 500) {
7490
+ return RpcError.networkError(message, {
7491
+ ...baseDetails,
7492
+ serverError: errorData
7232
7493
  });
7233
7494
  }
7234
- const accountKeys = accountTable.getPublicKeys();
7235
- const header = accountTable.getHeader();
7236
- const compiledInstructions = this.instructions.map((instruction) => {
7237
- const programIdIndex = accountTable.getIndex(instruction.programId);
7238
- if (programIdIndex === -1) {
7239
- throw new TransactionError(
7240
- "INVALID_INSTRUCTION" /* INVALID_INSTRUCTION */,
7241
- `Program ID ${instruction.programId.toString()} not found in account table`
7242
- );
7243
- }
7244
- const accountKeyIndexes = instruction.accounts.map((meta) => {
7245
- const index = accountTable.getIndex(meta.pubkey);
7246
- if (index === -1) {
7247
- throw new TransactionError(
7248
- "INVALID_INSTRUCTION" /* INVALID_INSTRUCTION */,
7249
- `Account ${meta.pubkey.toString()} not found in account table`
7250
- );
7495
+ return new RpcError("NETWORK_ERROR" /* NETWORK_ERROR */, message, baseDetails, isRetryable);
7496
+ }
7497
+ /**
7498
+ * Parse error response body to extract message and RPC error code.
7499
+ *
7500
+ * Handles multiple formats:
7501
+ * - JSON-RPC error: { error: { code, message, data? } }
7502
+ * - Simple JSON: { message: "..." }
7503
+ * - Non-JSON responses
7504
+ */
7505
+ async parseErrorResponse(response, status) {
7506
+ let message = `HTTP ${status}: ${response.statusText}`;
7507
+ let rpcCode;
7508
+ let errorData;
7509
+ try {
7510
+ errorData = await response.json();
7511
+ if (errorData && typeof errorData === "object") {
7512
+ const data = errorData;
7513
+ if (data.error && typeof data.error === "object" && "message" in data.error) {
7514
+ const rpcError = data.error;
7515
+ message = String(rpcError.message);
7516
+ rpcCode = typeof rpcError.code === "number" ? rpcError.code : void 0;
7517
+ } else if ("message" in data) {
7518
+ message = String(data.message);
7251
7519
  }
7252
- return index;
7253
- });
7254
- const compiled = {
7255
- programIdIndex,
7256
- accountKeyIndexes: Object.freeze(accountKeyIndexes),
7257
- data: instruction.data
7258
- };
7259
- return compiled;
7260
- });
7261
- const message = new Message(
7262
- header,
7263
- accountKeys,
7264
- this.recentBlockhash,
7265
- this.txCreationTime,
7266
- compiledInstructions
7267
- );
7268
- return Transaction.fromMessage(message);
7520
+ }
7521
+ } catch {
7522
+ }
7523
+ return { message, rpcCode, errorData };
7524
+ }
7525
+ /**
7526
+ * Returns the configured RPC endpoint URL.
7527
+ */
7528
+ getUrl() {
7529
+ return this.url;
7269
7530
  }
7270
7531
  };
7271
7532
 
7533
+ // src/rpc/index.ts
7534
+ function createRialoClient(config) {
7535
+ const { chain: chain2, transport } = config;
7536
+ const httpTransport = new HttpTransport(chain2.rpcUrl, transport);
7537
+ return new RialoClient(httpTransport, chain2);
7538
+ }
7539
+ function getDefaultRialoClientConfig(network) {
7540
+ switch (network) {
7541
+ case "mainnet":
7542
+ return { chain: RIALO_MAINNET_CHAIN };
7543
+ case "devnet":
7544
+ return { chain: RIALO_DEVNET_CHAIN };
7545
+ case "testnet":
7546
+ return { chain: RIALO_TESTNET_CHAIN };
7547
+ case "localnet":
7548
+ return { chain: RIALO_LOCALNET_CHAIN };
7549
+ default:
7550
+ throw new RpcError(
7551
+ "INVALID_NETWORK" /* INVALID_NETWORK */,
7552
+ `Unknown network: ${network}`
7553
+ );
7554
+ }
7555
+ }
7556
+
7272
7557
  // src/signer/keypair-signer.ts
7273
7558
  var KeypairSigner = class {
7274
7559
  constructor(keypair) {
@@ -7289,9 +7574,6 @@ var KeypairSigner = class {
7289
7574
  };
7290
7575
  /*! Bundled license information:
7291
7576
 
7292
- @scure/base/index.js:
7293
- (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7294
-
7295
7577
  @noble/ed25519/index.js:
7296
7578
  (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
7297
7579
 
@@ -7299,10 +7581,13 @@ var KeypairSigner = class {
7299
7581
  @noble/hashes/utils.js:
7300
7582
  (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7301
7583
 
7584
+ @scure/base/index.js:
7585
+ (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7586
+
7302
7587
  @scure/bip39/index.js:
7303
7588
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
7304
7589
  */
7305
7590
 
7306
- export { AccountMetaTable, BASE_DERIVATION_PATH, BLOCKHASH_LENGTH, BaseRpcClient, Blockhash, CryptoError, CryptoErrorCode, DEFAULT_NUM_ACCOUNTS, HttpTransport, KELVIN_PER_RLO, Keypair, KeypairSigner, Message, Mnemonic, PUBLIC_KEY_LENGTH, PublicKey, QueryRpcClient, RialoClient, RialoError, RialoErrorType, RpcError, RpcErrorCode, SECRET_KEY_LENGTH, SIGNATURE_LENGTH, SYSTEM_PROGRAM_ID, Signature, SystemInstruction, Transaction, TransactionBuilder, TransactionError, TransactionErrorCode, TransactionRpcClient, URL_DEVNET, URL_LOCALNET, URL_MAINNET, URL_TESTNET, calculateBackoff, createAccount, createBorshInstruction, createRialoClient, encodeBorshData, fromBase64, getDevnetUrl, getLocalnetUrl, getMainnetUrl, getTestnetUrl, sleep, toBase64, transferInstruction };
7591
+ export { AccountMetaTable, BASE_DERIVATION_PATH, BaseRpcClient, CryptoError, CryptoErrorCode, DEFAULT_NUM_ACCOUNTS, HttpTransport, KELVIN_PER_RLO, Keypair, KeypairSigner, Message, Mnemonic, PUBLIC_KEY_LENGTH, PublicKey, QueryRpcClient, RIALO_DEVNET_CHAIN, RIALO_LOCALNET_CHAIN, RIALO_MAINNET_CHAIN, RIALO_TESTNET_CHAIN, RialoClient, RialoError, RialoErrorType, RpcError, RpcErrorCode, SECRET_KEY_LENGTH, SIGNATURE_LENGTH, SYSTEM_PROGRAM_ID, Signature, SystemInstruction, Transaction, TransactionBuilder, TransactionError, TransactionErrorCode, TransactionRpcClient, URL_DEVNET, URL_LOCALNET, URL_MAINNET, URL_TESTNET, calculateBackoff, createAccount, createBorshInstruction, createRialoClient, encodeBorshData, fromBase64, getDefaultRialoClientConfig, getDevnetUrl, getLocalnetUrl, getMainnetUrl, getTestnetUrl, sleep, toBase64, transferInstruction };
7307
7592
  //# sourceMappingURL=index.mjs.map
7308
7593
  //# sourceMappingURL=index.mjs.map