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