@rialo/ts-cdk 0.1.2 → 0.1.3

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
@@ -455,13 +455,32 @@ var URL_MAINNET = "https://mainnet.rialo.io:4100";
455
455
  var URL_TESTNET = "https://testnet.rialo.io:4100";
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,1261 @@ 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
6056
- );
6057
- }
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
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 }))
6065
5964
  );
6066
5965
  }
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 */
6075
- };
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);
6079
- }
6080
- toJSON() {
6081
- return {
6082
- code: this.code,
6083
- message: this.message,
6084
- details: this.details,
6085
- retryable: this.retryable
6086
- };
6087
- }
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;
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);
6096
5975
  }
6097
5976
  /**
6098
- * Makes a JSON-RPC 2.0 method call with type safety.
5977
+ * Deserialize a message from wire format.
6099
5978
  *
6100
- * Handles request serialization, response validation, and error mapping.
5979
+ * @param data - Serialized message bytes
5980
+ * @returns Deserialized Message
6101
5981
  */
6102
- async call(method, params = []) {
6103
- const requestId = this.requestId++;
6104
- const request = {
6105
- jsonrpc: "2.0",
6106
- id: requestId,
6107
- method,
6108
- params
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++]
6109
5994
  };
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
- });
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
+ );
6118
6014
  }
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
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
6124
6061
  });
6125
6062
  }
6126
- if (!("result" in response)) {
6127
- throw RpcError.invalidResponse({
6128
- ...requestDetails,
6129
- response
6063
+ return new _Message(header, accountKeys, validFrom, instructions);
6064
+ }
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);
6130
6080
  });
6131
- }
6132
- return response.result;
6081
+ this.serializeCompactArray(buf, Array.from(ix.data), (b, byte) => {
6082
+ b.push(byte);
6083
+ });
6084
+ });
6085
+ return new Uint8Array(buffer);
6133
6086
  }
6134
- /**
6135
- * Validate JSON-RPC response structure
6136
- */
6137
- isValidJsonRpcResponse(data) {
6138
- if (typeof data !== "object" || data === null) {
6139
- return false;
6087
+ serializeCompactArray(buffer, items, serializeItem) {
6088
+ this.serializeCompactU16(buffer, items.length);
6089
+ for (const item of items) {
6090
+ serializeItem(buffer, item);
6140
6091
  }
6141
- const response = data;
6142
- return response.jsonrpc === "2.0" && typeof response.id === "number" && ("result" in response || "error" in response);
6143
- }
6144
- /**
6145
- * Returns the configured RPC endpoint URL.
6146
- */
6147
- getUrl() {
6148
- return this.transport.getUrl();
6149
6092
  }
6150
- };
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);
6093
+ serializeCompactU16(buffer, value) {
6094
+ if (value < 0 || value > 65535) {
6095
+ throw new Error(`Value out of range for compact-u16: ${value}`);
6160
6096
  }
6161
- return btoa(result);
6162
- }
6163
- if (typeof Buffer !== "undefined") {
6164
- return Buffer.from(bytes).toString("base64");
6165
- }
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);
6097
+ if (value <= 127) {
6098
+ buffer.push(value);
6099
+ return;
6174
6100
  }
6175
- return bytes;
6176
- }
6177
- if (typeof Buffer !== "undefined") {
6178
- return new Uint8Array(Buffer.from(base64, "base64"));
6101
+ if (value <= 16383) {
6102
+ buffer.push(value & 127 | 128);
6103
+ buffer.push(value >> 7 & 127);
6104
+ return;
6105
+ }
6106
+ buffer.push(value & 127 | 128);
6107
+ buffer.push(value >> 7 & 127 | 128);
6108
+ buffer.push(value >> 14 & 255);
6179
6109
  }
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;
6201
- }
6202
-
6203
- // src/rpc/clients/query-client.ts
6204
- var QueryRpcClient = class extends BaseRpcClient {
6205
6110
  /**
6206
- * Get the latest blockhash from the blockchain
6111
+ * Get all signers required for this message.
6207
6112
  */
6208
- async getLatestBlockhash() {
6209
- const result = await this.call(
6210
- "getLatestBlockhash",
6211
- []
6212
- );
6213
- return Blockhash.fromString(result.value.blockhash);
6113
+ getSigners() {
6114
+ return this.accountKeys.slice(0, this.header.numRequiredSignatures);
6214
6115
  }
6215
6116
  /**
6216
- * Get the balance of an account
6117
+ * Check if a public key is a required signer.
6217
6118
  */
6218
- async getBalance(pubkey) {
6219
- const result = await this.call("getBalance", [
6220
- { address: pubkey.toString() }
6221
- ]);
6222
- return BigInt(result.value);
6119
+ isSignerRequired(pubkey) {
6120
+ return this.getSigners().some((signer) => signer.equals(pubkey));
6223
6121
  }
6224
6122
  /**
6225
- * Get detailed information about an account
6123
+ * Get the index of a signer in the signers array.
6124
+ * Returns -1 if not a signer.
6226
6125
  */
6227
- async getAccountInfo(pubkey) {
6228
- const result = await this.call("getAccountInfo", [{ address: pubkey.toString(), encoding: "base64" }]);
6229
- if (!result.value) {
6230
- return null;
6231
- }
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
- };
6126
+ getSignerIndex(pubkey) {
6127
+ return this.getSigners().findIndex((signer) => signer.equals(pubkey));
6239
6128
  }
6240
- /**
6241
- * Get the current block height
6242
- */
6243
- async getBlockHeight() {
6244
- const result = await this.call("getBlockHeight", []);
6245
- return BigInt(result);
6129
+ };
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
+ );
6246
6137
  }
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;
6138
+ const firstByte = data[cursor++];
6139
+ if ((firstByte & 128) === 0) {
6140
+ return [firstByte, cursor];
6141
+ }
6142
+ if (cursor >= data.length) {
6143
+ throw new TransactionError(
6144
+ "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6145
+ "Incomplete compact-u16 encoding"
6146
+ );
6147
+ }
6148
+ const secondByte = data[cursor++];
6149
+ if ((secondByte & 128) === 0) {
6150
+ return [firstByte & 127 | secondByte << 7, cursor];
6151
+ }
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];
6161
+ }
6162
+
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
+ );
6254
6178
  }
6255
- return {
6256
- signature,
6257
- slot: BigInt(result.slot),
6258
- blockTime: result.blockTime ? BigInt(result.blockTime) : void 0,
6259
- err: result.err
6260
- };
6261
6179
  }
6262
6180
  /**
6263
- * Get the total number of transactions processed since genesis
6181
+ * Create an unsigned transaction from a message.
6182
+ * All signature slots are initialized to zero.
6183
+ *
6184
+ * @internal - Users should use TransactionBuilder instead
6264
6185
  */
6265
- async getTransactionCount() {
6266
- const result = await this.call("getTransactionCount", []);
6267
- return BigInt(result);
6186
+ static fromMessage(message) {
6187
+ const numSignatures = message.header.numRequiredSignatures;
6188
+ const signatures = Array.from(
6189
+ { length: numSignatures },
6190
+ () => new Uint8Array(SIGNATURE_LENGTH)
6191
+ );
6192
+ return new _Transaction(message, signatures);
6268
6193
  }
6269
6194
  /**
6270
- * Get the status of multiple transaction signatures
6195
+ * Create transaction from message and existing signatures.
6196
+ * @internal
6271
6197
  */
6272
- async getSignatureStatuses(signatures) {
6273
- const result = await this.call("getSignatureStatuses", [signatures]);
6274
- return result.value.map((status) => {
6275
- if (!status) {
6276
- return null;
6198
+ static fromMessageAndSignatures(message, signatures) {
6199
+ return new _Transaction(message, signatures);
6200
+ }
6201
+ /**
6202
+ * Deserialize a transaction from wire format.
6203
+ */
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
+ );
6210
+ }
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
+ );
6277
6221
  }
6278
- return {
6279
- slot: BigInt(status.slot),
6280
- confirmations: status.confirmations,
6281
- err: status.err
6282
- };
6283
- });
6222
+ const signature = data.slice(cursor, cursor + SIGNATURE_LENGTH);
6223
+ signatures.push(signature);
6224
+ cursor += SIGNATURE_LENGTH;
6225
+ }
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;
6284
6238
  }
6285
6239
  /**
6286
- * Get epoch information
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
+ * ```
6287
6251
  */
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
- };
6252
+ sign(keypair) {
6253
+ const messageBytes = this.message.serialize();
6254
+ const signature = keypair.sign(messageBytes);
6255
+ return this.addSignatureForPubkey(keypair.publicKey, signature);
6298
6256
  }
6299
6257
  /**
6300
- * Get the health status of the node
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
+ * ```
6301
6265
  */
6302
- async getHealth() {
6303
- const result = await this.call("getHealth", []);
6266
+ signAll(keypairs) {
6267
+ let result = this;
6268
+ for (const keypair of keypairs) {
6269
+ result = result.sign(keypair);
6270
+ }
6304
6271
  return result;
6305
6272
  }
6306
- };
6307
-
6308
- // src/rpc/clients/transaction-client.ts
6309
- var TransactionRpcClient = class extends BaseRpcClient {
6310
6273
  /**
6311
- * Submit a signed transaction to the blockchain
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
+ * ```
6312
6281
  */
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;
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);
6325
6287
  }
6326
6288
  /**
6327
- * Request an airdrop of tokens to an account (devnet/testnet only)
6289
+ * Sign with multiple signers.
6290
+ * Returns a NEW Transaction instance.
6328
6291
  */
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);
6292
+ async signAllWith(signers) {
6293
+ let result = this;
6294
+ for (const signer of signers) {
6295
+ result = await result.signWith(signer);
6296
+ }
6297
+ return result;
6347
6298
  }
6348
6299
  /**
6349
- * Returns the configured RPC endpoint URL.
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
+ * ```
6350
6309
  */
6351
- getUrl() {
6352
- return this.transport.getUrl();
6310
+ partialSign(keypair) {
6311
+ return this.sign(keypair);
6353
6312
  }
6354
6313
  /**
6355
- * Retrieves the latest blockhash from the blockchain.
6356
- *
6357
- * Required for transaction creation and replay protection.
6314
+ * Partially sign with a Signer interface (async).
6315
+ * Returns a NEW Transaction instance.
6358
6316
  */
6359
- async getLatestBlockhash() {
6360
- return await this.queryClient.getLatestBlockhash();
6317
+ async partialSignWith(signer) {
6318
+ return this.signWith(signer);
6361
6319
  }
6362
6320
  /**
6363
- * Retrieves the balance of an account in kelvins (smallest unit).
6321
+ * Add a signature at a specific index.
6322
+ * Returns a NEW Transaction instance.
6323
+ *
6324
+ * Most users should use sign() or signAll() instead.
6364
6325
  */
6365
- async getBalance(pubkey) {
6366
- return await this.queryClient.getBalance(pubkey);
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);
6367
6344
  }
6368
6345
  /**
6369
- * Retrieves detailed information about an account.
6346
+ * Add a signature for a specific public key.
6347
+ * Returns a NEW Transaction instance.
6370
6348
  *
6371
- * @returns Account info or null if account doesn't exist
6349
+ * Most users should use sign() or signAll() instead.
6372
6350
  */
6373
- async getAccountInfo(pubkey) {
6374
- return await this.queryClient.getAccountInfo(pubkey);
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);
6375
6357
  }
6376
6358
  /**
6377
- * Retrieves the current block height.
6359
+ * Check if transaction is fully signed (all signatures present).
6378
6360
  */
6379
- async getBlockHeight() {
6380
- return await this.queryClient.getBlockHeight();
6361
+ isSigned() {
6362
+ return this.signatures.every((sig) => sig.some((byte) => byte !== 0));
6381
6363
  }
6382
6364
  /**
6383
- * Retrieves detailed information about a transaction.
6384
- *
6385
- * @returns Transaction info or null if transaction not found
6365
+ * Check if a specific signature slot is filled.
6386
6366
  */
6387
- async getTransaction(signature) {
6388
- return await this.queryClient.getTransaction(signature);
6367
+ isSignaturePresent(index) {
6368
+ if (index < 0 || index >= this.signatures.length) {
6369
+ return false;
6370
+ }
6371
+ return this.signatures[index].some((byte) => byte !== 0);
6389
6372
  }
6390
6373
  /**
6391
- * Retrieves the total number of transactions processed since genesis.
6374
+ * Get all signatures (returns copies to prevent mutation).
6392
6375
  */
6393
- async getTransactionCount() {
6394
- return await this.queryClient.getTransactionCount();
6376
+ getSignatures() {
6377
+ return this.signatures.map((sig) => new Uint8Array(sig));
6395
6378
  }
6396
6379
  /**
6397
- * Retrieves the status of multiple transaction signatures.
6380
+ * Get a specific signature (returns copy).
6398
6381
  */
6399
- async getSignatureStatuses(signatures) {
6400
- return await this.queryClient.getSignatureStatuses(signatures);
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]);
6401
6390
  }
6402
6391
  /**
6403
- * Retrieves current epoch information.
6392
+ * Get a specific signature for a public key.
6404
6393
  */
6405
- async getEpochInfo() {
6406
- return await this.queryClient.getEpochInfo();
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);
6407
6400
  }
6408
6401
  /**
6409
- * Checks the health status of the RPC node.
6410
- *
6411
- * @returns "ok" if healthy, error message otherwise
6402
+ * Get required signers for this transaction.
6412
6403
  */
6413
- async getHealth() {
6414
- return await this.queryClient.getHealth();
6404
+ getSigners() {
6405
+ return this.message.getSigners();
6415
6406
  }
6416
6407
  /**
6417
- * Submits a signed transaction to the blockchain.
6418
- *
6419
- * @param transaction - Serialized signed transaction bytes
6420
- * @param options - Transaction submission options
6421
- * @returns Transaction signature
6408
+ * Get the number of required signatures.
6422
6409
  */
6423
- async sendTransaction(transaction, options) {
6424
- return await this.transactionClient.sendTransaction(transaction, options);
6410
+ getRequiredSignatureCount() {
6411
+ return this.message.header.numRequiredSignatures;
6425
6412
  }
6426
6413
  /**
6427
- * Requests an airdrop of tokens to an account.
6414
+ * Throw an error if the transaction is not fully signed.
6428
6415
  *
6429
- * **Note**: Only available on devnet and testnet.
6416
+ * @throws {TransactionError} If transaction is not fully signed
6430
6417
  *
6431
- * @param pubkey - Account to receive the airdrop
6432
- * @param amount - Amount in kelvins (smallest unit)
6433
- * @returns Transaction signature
6418
+ * @example
6419
+ * ```typescript
6420
+ * signedTx.ensureSigned(); // Throws if not signed
6421
+ * await client.sendTransaction(signedTx.serialize());
6422
+ * ```
6434
6423
  */
6435
- async requestAirdrop(pubkey, amount) {
6436
- return await this.transactionClient.requestAirdrop(pubkey, amount);
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
+ }
6435
+ }
6436
+ /**
6437
+ * Serialize transaction to wire format.
6438
+ */
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
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
+ * ```
6632
6524
  */
6633
- static deserialize(data) {
6634
- if (data.length < 3) {
6525
+ build() {
6526
+ if (!this.payer) {
6635
6527
  throw new TransactionError(
6636
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6637
- "Insufficient data for message header"
6528
+ "INVALID_ACCOUNT_META" /* INVALID_ACCOUNT_META */,
6529
+ "Transaction must have a fee payer. Use setPayer() to set the fee payer."
6638
6530
  );
6639
6531
  }
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) {
6532
+ if (!this.validFrom) {
6661
6533
  throw new TransactionError(
6662
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6663
- "Insufficient data for blockhash"
6534
+ "INVALID_MESSAGE_FORMAT" /* INVALID_MESSAGE_FORMAT */,
6535
+ "Transaction must have a valid from. Use setValidFrom() to set the valid from."
6664
6536
  );
6665
6537
  }
6666
- const recentBlockhash = Blockhash.fromBytes(
6667
- data.slice(cursor, cursor + 32)
6668
- );
6669
- cursor += 32;
6670
- if (data.length < cursor + 8) {
6671
- throw new TransactionError(
6672
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6673
- "Insufficient data for TxCreationTime"
6674
- );
6538
+ if (this.instructions.length === 0) {
6539
+ throw TransactionError.noInstructions();
6675
6540
  }
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) {
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);
6748
- }
6749
- serializeCompactArray(buffer, items, serializeItem) {
6750
- this.serializeCompactU16(buffer, items.length);
6751
- for (const item of items) {
6752
- serializeItem(buffer, item);
6753
- }
6582
+ const message = new Message(
6583
+ header,
6584
+ accountKeys,
6585
+ this.validFrom,
6586
+ compiledInstructions
6587
+ );
6588
+ return Transaction.fromMessage(message);
6754
6589
  }
6755
- serializeCompactU16(buffer, value) {
6756
- if (value < 0 || value > 65535) {
6757
- throw new Error(`Value out of range for compact-u16: ${value}`);
6758
- }
6759
- if (value <= 127) {
6760
- buffer.push(value);
6761
- return;
6762
- }
6763
- if (value <= 16383) {
6764
- buffer.push(value & 127 | 128);
6765
- buffer.push(value >> 7 & 127);
6766
- return;
6767
- }
6768
- buffer.push(value & 127 | 128);
6769
- buffer.push(value >> 7 & 127 | 128);
6770
- buffer.push(value >> 14 & 255);
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["ACCOUNT_NOT_FOUND"] = "ACCOUNT_NOT_FOUND";
6607
+ RpcErrorCode2["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED";
6608
+ RpcErrorCode2["NODE_UNHEALTHY"] = "NODE_UNHEALTHY";
6609
+ return RpcErrorCode2;
6610
+ })(RpcErrorCode || {});
6611
+ var RpcError = class _RpcError extends Error {
6612
+ code;
6613
+ details;
6614
+ retryable;
6615
+ constructor(code, message, details = {}, retryable = false) {
6616
+ super(message);
6617
+ this.name = "RpcError";
6618
+ this.code = code;
6619
+ this.details = details;
6620
+ this.retryable = retryable;
6771
6621
  }
6772
- /**
6773
- * Get all signers required for this message.
6774
- */
6775
- getSigners() {
6776
- return this.accountKeys.slice(0, this.header.numRequiredSignatures);
6622
+ static requestTimeout(timeoutMs, details) {
6623
+ return new _RpcError(
6624
+ "REQUEST_TIMEOUT" /* REQUEST_TIMEOUT */,
6625
+ `RPC request timed out after ${timeoutMs}ms. The node may be slow or unreachable.`,
6626
+ { ...details, timeout: timeoutMs },
6627
+ true
6628
+ // Retryable
6629
+ );
6777
6630
  }
6778
- /**
6779
- * Check if a public key is a required signer.
6780
- */
6781
- isSignerRequired(pubkey) {
6782
- return this.getSigners().some((signer) => signer.equals(pubkey));
6631
+ static networkError(message, details) {
6632
+ return new _RpcError(
6633
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
6634
+ `Network error: ${message}. Check your internet connection and node URL.`,
6635
+ details,
6636
+ true
6637
+ // Retryable
6638
+ );
6783
6639
  }
6784
- /**
6785
- * Get the index of a signer in the signers array.
6786
- * Returns -1 if not a signer.
6787
- */
6788
- getSignerIndex(pubkey) {
6789
- return this.getSigners().findIndex((signer) => signer.equals(pubkey));
6640
+ static invalidResponse(details) {
6641
+ return new _RpcError(
6642
+ "INVALID_RESPONSE" /* INVALID_RESPONSE */,
6643
+ "Received invalid response from RPC node. The response format is unexpected.",
6644
+ details,
6645
+ false
6646
+ );
6790
6647
  }
6791
- };
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"
6648
+ static accountNotFound(pubkey) {
6649
+ return new _RpcError(
6650
+ "ACCOUNT_NOT_FOUND" /* ACCOUNT_NOT_FOUND */,
6651
+ `Account ${pubkey} not found on chain. It may not exist or has zero balance.`,
6652
+ { pubkey },
6653
+ false
6798
6654
  );
6799
6655
  }
6800
- const firstByte = data[cursor++];
6801
- if ((firstByte & 128) === 0) {
6802
- return [firstByte, cursor];
6803
- }
6804
- if (cursor >= data.length) {
6805
- throw new TransactionError(
6806
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6807
- "Incomplete compact-u16 encoding"
6656
+ static rateLimitExceeded(details) {
6657
+ return new _RpcError(
6658
+ "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */,
6659
+ "Rate limit exceeded. Too many requests to the RPC endpoint. Try again later or use a different endpoint.",
6660
+ details,
6661
+ true
6662
+ // Can retry after delay
6808
6663
  );
6809
6664
  }
6810
- const secondByte = data[cursor++];
6811
- if ((secondByte & 128) === 0) {
6812
- return [firstByte & 127 | secondByte << 7, cursor];
6665
+ static fromRpcCode(rpcCode, message, details) {
6666
+ const codeMap = {
6667
+ [-32700]: "PARSE_ERROR" /* PARSE_ERROR */,
6668
+ [-32600]: "INVALID_REQUEST" /* INVALID_REQUEST */,
6669
+ [-32601]: "METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
6670
+ [-32602]: "INVALID_PARAMS" /* INVALID_PARAMS */,
6671
+ [-32603]: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
6672
+ [429]: "RATE_LIMIT_EXCEEDED" /* RATE_LIMIT_EXCEEDED */
6673
+ };
6674
+ const code = codeMap[rpcCode] || "INTERNAL_ERROR" /* INTERNAL_ERROR */;
6675
+ const retryable = rpcCode === 429 || rpcCode === -32603;
6676
+ return new _RpcError(code, message, { ...details, rpcCode }, retryable);
6813
6677
  }
6814
- if (cursor >= data.length) {
6815
- throw new TransactionError(
6816
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6817
- "Incomplete compact-u16 encoding"
6818
- );
6678
+ toJSON() {
6679
+ return {
6680
+ code: this.code,
6681
+ message: this.message,
6682
+ details: this.details,
6683
+ retryable: this.retryable
6684
+ };
6819
6685
  }
6820
- const thirdByte = data[cursor++];
6821
- const value = firstByte & 127 | (secondByte & 127) << 7 | thirdByte << 14;
6822
- return [value, cursor];
6823
- }
6686
+ };
6824
6687
 
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
- }
6688
+ // src/rpc/clients/base-client.ts
6689
+ var BaseRpcClient = class {
6690
+ transport;
6691
+ requestId = 1;
6692
+ constructor(transport) {
6693
+ this.transport = transport;
6841
6694
  }
6842
6695
  /**
6843
- * Create an unsigned transaction from a message.
6844
- * All signature slots are initialized to zero.
6696
+ * Makes a JSON-RPC 2.0 method call with type safety.
6845
6697
  *
6846
- * @internal - Users should use TransactionBuilder instead
6698
+ * Handles request serialization, response validation, and error mapping.
6847
6699
  */
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);
6700
+ async call(method, params = []) {
6701
+ const requestId = this.requestId++;
6702
+ const request = {
6703
+ jsonrpc: "2.0",
6704
+ id: requestId,
6705
+ method,
6706
+ params
6707
+ };
6708
+ const requestBody = JSON.stringify(request);
6709
+ const requestDetails = { method, params, requestId };
6710
+ const data = await this.transport.request(requestBody, requestDetails);
6711
+ if (!this.isValidJsonRpcResponse(data)) {
6712
+ throw RpcError.invalidResponse({
6713
+ ...requestDetails,
6714
+ response: data
6715
+ });
6716
+ }
6717
+ const response = data;
6718
+ if (response.error) {
6719
+ throw RpcError.fromRpcCode(response.error.code, response.error.message, {
6720
+ ...requestDetails,
6721
+ rpcData: response.error.data
6722
+ });
6723
+ }
6724
+ if (!("result" in response)) {
6725
+ throw RpcError.invalidResponse({
6726
+ ...requestDetails,
6727
+ response
6728
+ });
6729
+ }
6730
+ return response.result;
6855
6731
  }
6856
6732
  /**
6857
- * Create transaction from message and existing signatures.
6858
- * @internal
6733
+ * Validate JSON-RPC response structure
6859
6734
  */
6860
- static fromMessageAndSignatures(message, signatures) {
6861
- return new _Transaction(message, signatures);
6735
+ isValidJsonRpcResponse(data) {
6736
+ if (typeof data !== "object" || data === null) {
6737
+ return false;
6738
+ }
6739
+ const response = data;
6740
+ return response.jsonrpc === "2.0" && typeof response.id === "number" && ("result" in response || "error" in response);
6862
6741
  }
6863
6742
  /**
6864
- * Deserialize a transaction from wire format.
6743
+ * Returns the configured RPC endpoint URL.
6865
6744
  */
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;
6745
+ getUrl() {
6746
+ return this.transport.getUrl();
6747
+ }
6748
+ };
6749
+
6750
+ // src/utils.ts
6751
+ function toBase64(bytes) {
6752
+ if (typeof btoa !== "undefined") {
6753
+ const chunkSize = 8192;
6754
+ let result = "";
6755
+ for (let i = 0; i < bytes.length; i += chunkSize) {
6756
+ const chunk = bytes.slice(i, i + chunkSize);
6757
+ result += String.fromCharCode(...chunk);
6887
6758
  }
6888
- if (cursor >= data.length) {
6889
- throw new TransactionError(
6890
- "INSUFFICIENT_DATA" /* INSUFFICIENT_DATA */,
6891
- "No message data found after signatures"
6892
- );
6759
+ return btoa(result);
6760
+ }
6761
+ if (typeof Buffer !== "undefined") {
6762
+ return Buffer.from(bytes).toString("base64");
6763
+ }
6764
+ throw new Error("No base64 encoding available in this environment");
6765
+ }
6766
+ function fromBase64(base64) {
6767
+ if (typeof atob !== "undefined") {
6768
+ const binary = atob(base64);
6769
+ const bytes = new Uint8Array(binary.length);
6770
+ for (let i = 0; i < binary.length; i++) {
6771
+ bytes[i] = binary.charCodeAt(i);
6893
6772
  }
6894
- const messageBytes = data.slice(cursor);
6895
- const message = Message.deserialize(messageBytes);
6896
- return new _Transaction(message, signatures);
6773
+ return bytes;
6897
6774
  }
6898
- getMessage() {
6899
- return this.message;
6775
+ if (typeof Buffer !== "undefined") {
6776
+ return new Uint8Array(Buffer.from(base64, "base64"));
6900
6777
  }
6778
+ throw new Error("No base64 decoding available in this environment");
6779
+ }
6780
+ function sleep(ms) {
6781
+ return new Promise((resolve) => setTimeout(resolve, ms));
6782
+ }
6783
+ function calculateBackoff(attempt, baseMs = 1e3, maxMs = 3e4) {
6784
+ const exponentialDelay = baseMs * 2 ** attempt;
6785
+ const jitter = Math.random() * 0.3 * exponentialDelay;
6786
+ return Math.min(exponentialDelay + jitter, maxMs);
6787
+ }
6788
+ function getDevnetUrl() {
6789
+ return URL_DEVNET;
6790
+ }
6791
+ function getTestnetUrl() {
6792
+ return URL_TESTNET;
6793
+ }
6794
+ function getMainnetUrl() {
6795
+ return URL_MAINNET;
6796
+ }
6797
+ function getLocalnetUrl() {
6798
+ return URL_LOCALNET;
6799
+ }
6800
+
6801
+ // src/rpc/clients/query-client.ts
6802
+ var QueryRpcClient = class extends BaseRpcClient {
6901
6803
  /**
6902
- * Sign the transaction with a keypair.
6903
- * Returns a NEW Transaction instance.
6904
- *
6905
- * @param keypair - Keypair to sign with
6906
- * @returns New Transaction instance with signature added
6907
- *
6908
- * @example
6909
- * ```typescript
6910
- * const signedTx = tx.sign(keypair);
6911
- * await client.sendTransaction(signedTx.serialize());
6912
- * ```
6804
+ * Get the balance of an account
6913
6805
  */
6914
- sign(keypair) {
6915
- const messageBytes = this.message.serialize();
6916
- const signature = keypair.sign(messageBytes);
6917
- return this.addSignatureForPubkey(keypair.publicKey, signature);
6806
+ async getBalance(pubkey) {
6807
+ const result = await this.call("getBalance", [
6808
+ { address: pubkey.toString() }
6809
+ ]);
6810
+ return BigInt(result.value);
6918
6811
  }
6919
6812
  /**
6920
- * Sign with multiple keypairs at once.
6921
- * Returns a NEW Transaction instance.
6922
- *
6923
- * @example
6924
- * ```typescript
6925
- * const signed = tx.signAll([keypair1, keypair2, keypair3]);
6926
- * ```
6813
+ * Get detailed information about an account
6927
6814
  */
6928
- signAll(keypairs) {
6929
- let result = this;
6930
- for (const keypair of keypairs) {
6931
- result = result.sign(keypair);
6815
+ async getAccountInfo(pubkey) {
6816
+ const result = await this.call("getAccountInfo", [{ address: pubkey.toString(), encoding: "base64" }]);
6817
+ if (!result.value) {
6818
+ return null;
6932
6819
  }
6933
- return result;
6820
+ return {
6821
+ balance: BigInt(result.value.balance),
6822
+ owner: PublicKey.fromString(result.value.owner),
6823
+ data: fromBase64(result.value.data),
6824
+ executable: result.value.executable,
6825
+ rentEpoch: BigInt(result.value.rentEpoch)
6826
+ };
6934
6827
  }
6935
6828
  /**
6936
- * Sign the transaction with a Signer interface (async).
6937
- * Returns a NEW Transaction instance.
6938
- *
6939
- * @example
6940
- * ```typescript
6941
- * const signedTx = await tx.signWith(browserWallet);
6942
- * ```
6829
+ * Get the current block height
6943
6830
  */
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);
6831
+ async getBlockHeight() {
6832
+ const result = await this.call("getBlockHeight", []);
6833
+ return BigInt(result);
6949
6834
  }
6950
6835
  /**
6951
- * Sign with multiple signers.
6952
- * Returns a NEW Transaction instance.
6836
+ * Get detailed information about a transaction
6953
6837
  */
6954
- async signAllWith(signers) {
6955
- let result = this;
6956
- for (const signer of signers) {
6957
- result = await result.signWith(signer);
6838
+ async getTransaction(signature) {
6839
+ const result = await this.call("getTransaction", [signature]);
6840
+ if (!result) {
6841
+ return null;
6958
6842
  }
6959
- return result;
6843
+ return {
6844
+ signature,
6845
+ slot: BigInt(result.slot),
6846
+ blockTime: result.blockTime ? BigInt(result.blockTime) : void 0,
6847
+ err: result.err
6848
+ };
6960
6849
  }
6961
6850
  /**
6962
- * Partially sign the transaction (for multi-sig transactions).
6963
- * Returns a NEW Transaction instance.
6964
- *
6965
- * @example
6966
- * ```typescript
6967
- * const signedTx = tx
6968
- * .partialSign(signer1)
6969
- * .partialSign(signer2);
6970
- * ```
6851
+ * Get the total number of transactions processed since genesis
6971
6852
  */
6972
- partialSign(keypair) {
6973
- return this.sign(keypair);
6853
+ async getTransactionCount() {
6854
+ const result = await this.call("getTransactionCount", []);
6855
+ return BigInt(result);
6974
6856
  }
6975
6857
  /**
6976
- * Partially sign with a Signer interface (async).
6977
- * Returns a NEW Transaction instance.
6858
+ * Get the status of multiple transaction signatures
6978
6859
  */
6979
- async partialSignWith(signer) {
6980
- return this.signWith(signer);
6860
+ async getSignatureStatuses(signatures) {
6861
+ const result = await this.call("getSignatureStatuses", [signatures]);
6862
+ return result.value.map((status) => {
6863
+ if (!status) {
6864
+ return null;
6865
+ }
6866
+ return {
6867
+ slot: BigInt(status.slot),
6868
+ confirmations: status.confirmations,
6869
+ err: status.err
6870
+ };
6871
+ });
6981
6872
  }
6982
6873
  /**
6983
- * Add a signature at a specific index.
6984
- * Returns a NEW Transaction instance.
6985
- *
6986
- * Most users should use sign() or signAll() instead.
6874
+ * Get epoch information
6987
6875
  */
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}`
7000
- );
7001
- }
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);
6876
+ async getEpochInfo() {
6877
+ const result = await this.call("getEpochInfo", []);
6878
+ return {
6879
+ epoch: BigInt(result.epoch),
6880
+ slotIndex: BigInt(result.slotIndex),
6881
+ slotsInEpoch: BigInt(result.slotsInEpoch),
6882
+ absoluteSlot: BigInt(result.absoluteSlot),
6883
+ blockHeight: BigInt(result.blockHeight),
6884
+ transactionCount: result.transactionCount ? BigInt(result.transactionCount) : void 0
6885
+ };
7006
6886
  }
7007
6887
  /**
7008
- * Add a signature for a specific public key.
7009
- * Returns a NEW Transaction instance.
7010
- *
7011
- * Most users should use sign() or signAll() instead.
6888
+ * Get the health status of the node
7012
6889
  */
7013
- addSignatureForPubkey(pubkey, signature) {
7014
- const signerIndex = this.message.getSignerIndex(pubkey);
7015
- if (signerIndex === -1) {
7016
- throw TransactionError.signerNotFound(pubkey.toString());
7017
- }
7018
- return this.addSignature(signerIndex, signature);
6890
+ async getHealth() {
6891
+ const result = await this.call("getHealth", []);
6892
+ return result;
7019
6893
  }
6894
+ };
6895
+
6896
+ // src/rpc/clients/transaction-client.ts
6897
+ var TransactionRpcClient = class extends BaseRpcClient {
7020
6898
  /**
7021
- * Check if transaction is fully signed (all signatures present).
6899
+ * Submit a signed transaction to the blockchain
7022
6900
  */
7023
- isSigned() {
7024
- return this.signatures.every((sig) => sig.some((byte) => byte !== 0));
6901
+ async sendTransaction(transaction, options) {
6902
+ const base64Tx = toBase64(transaction);
6903
+ const config = {
6904
+ encoding: "base64",
6905
+ skipPreflight: options?.skipPreflight ?? false,
6906
+ maxRetries: options?.maxRetries ?? 5
6907
+ };
6908
+ const signature = await this.call("sendTransaction", [
6909
+ base64Tx,
6910
+ config
6911
+ ]);
6912
+ return signature;
7025
6913
  }
7026
6914
  /**
7027
- * Check if a specific signature slot is filled.
6915
+ * Request an airdrop of tokens to an account (devnet/testnet only)
7028
6916
  */
7029
- isSignaturePresent(index) {
7030
- if (index < 0 || index >= this.signatures.length) {
7031
- return false;
7032
- }
7033
- return this.signatures[index].some((byte) => byte !== 0);
6917
+ async requestAirdrop(pubkey, amount) {
6918
+ const signature = await this.call("requestAirdrop", [
6919
+ pubkey.toString(),
6920
+ Number(amount)
6921
+ ]);
6922
+ return signature;
6923
+ }
6924
+ };
6925
+
6926
+ // src/rpc/clients/client.ts
6927
+ var RialoClient = class {
6928
+ queryClient;
6929
+ transactionClient;
6930
+ transport;
6931
+ chain;
6932
+ constructor(transport, chain2) {
6933
+ this.chain = chain2;
6934
+ this.transport = transport;
6935
+ this.queryClient = new QueryRpcClient(transport);
6936
+ this.transactionClient = new TransactionRpcClient(transport);
7034
6937
  }
7035
6938
  /**
7036
- * Get all signatures (returns copies to prevent mutation).
6939
+ * Returns the configured RPC endpoint URL.
7037
6940
  */
7038
- getSignatures() {
7039
- return this.signatures.map((sig) => new Uint8Array(sig));
6941
+ getUrl() {
6942
+ return this.transport.getUrl();
7040
6943
  }
7041
6944
  /**
7042
- * Get a specific signature (returns copy).
6945
+ * Returns the chain identifier.
7043
6946
  */
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]);
6947
+ getChainIdentifier() {
6948
+ return this.chain.id;
7052
6949
  }
7053
6950
  /**
7054
- * Get a specific signature for a public key.
6951
+ * Retrieves the balance of an account in kelvins (smallest unit).
7055
6952
  */
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);
6953
+ async getBalance(pubkey) {
6954
+ return await this.queryClient.getBalance(pubkey);
7062
6955
  }
7063
6956
  /**
7064
- * Get required signers for this transaction.
6957
+ * Retrieves detailed information about an account.
6958
+ *
6959
+ * @returns Account info or null if account doesn't exist
7065
6960
  */
7066
- getSigners() {
7067
- return this.message.getSigners();
6961
+ async getAccountInfo(pubkey) {
6962
+ return await this.queryClient.getAccountInfo(pubkey);
7068
6963
  }
7069
6964
  /**
7070
- * Get the number of required signatures.
6965
+ * Retrieves the current block height.
7071
6966
  */
7072
- getRequiredSignatureCount() {
7073
- return this.message.header.numRequiredSignatures;
6967
+ async getBlockHeight() {
6968
+ return await this.queryClient.getBlockHeight();
7074
6969
  }
7075
6970
  /**
7076
- * Throw an error if the transaction is not fully signed.
7077
- *
7078
- * @throws {TransactionError} If transaction is not fully signed
6971
+ * Retrieves detailed information about a transaction.
7079
6972
  *
7080
- * @example
7081
- * ```typescript
7082
- * signedTx.ensureSigned(); // Throws if not signed
7083
- * await client.sendTransaction(signedTx.serialize());
7084
- * ```
6973
+ * @returns Transaction info or null if transaction not found
7085
6974
  */
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
- }
6975
+ async getTransaction(signature) {
6976
+ return await this.queryClient.getTransaction(signature);
7097
6977
  }
7098
6978
  /**
7099
- * Serialize transaction to wire format.
6979
+ * Retrieves the total number of transactions processed since genesis.
7100
6980
  */
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;
6981
+ async getTransactionCount() {
6982
+ return await this.queryClient.getTransactionCount();
7115
6983
  }
7116
- };
7117
-
7118
- // src/transaction/transaction-builder.ts
7119
- var TransactionBuilder = class _TransactionBuilder {
7120
- payer;
7121
- recentBlockhash;
7122
- txCreationTime;
7123
- instructions = [];
7124
- constructor() {
6984
+ /**
6985
+ * Retrieves the status of multiple transaction signatures.
6986
+ */
6987
+ async getSignatureStatuses(signatures) {
6988
+ return await this.queryClient.getSignatureStatuses(signatures);
7125
6989
  }
7126
6990
  /**
7127
- * Create a new transaction builder.
6991
+ * Retrieves current epoch information.
7128
6992
  */
7129
- static create() {
7130
- return new _TransactionBuilder();
6993
+ async getEpochInfo() {
6994
+ return await this.queryClient.getEpochInfo();
7131
6995
  }
7132
6996
  /**
7133
- * Set the fee payer for this transaction.
7134
- *
7135
- * The payer will be the first account and must sign the transaction.
7136
- * The payer pays for transaction fees.
6997
+ * Checks the health status of the RPC node.
7137
6998
  *
7138
- * @param payer - Public key of the fee payer
6999
+ * @returns "ok" if healthy, error message otherwise
7139
7000
  */
7140
- setPayer(payer) {
7141
- this.payer = payer;
7142
- return this;
7001
+ async getHealth() {
7002
+ return await this.queryClient.getHealth();
7143
7003
  }
7144
7004
  /**
7145
- * Set the recent blockhash for replay protection.
7146
- *
7147
- * Get this from client.getLatestBlockhash().
7148
- * Transactions are only valid for ~60 seconds after the blockhash.
7005
+ * Submits a signed transaction to the blockchain.
7149
7006
  *
7150
- * @param blockhash - Recent blockhash from the network
7007
+ * @param transaction - Serialized signed transaction bytes
7008
+ * @param options - Transaction submission options
7009
+ * @returns Transaction signature
7151
7010
  */
7152
- setRecentBlockhash(blockhash) {
7153
- this.recentBlockhash = blockhash;
7154
- return this;
7011
+ async sendTransaction(transaction, options) {
7012
+ return await this.transactionClient.sendTransaction(transaction, options);
7155
7013
  }
7156
7014
  /**
7157
- * Set the transaction creation timestamp.
7015
+ * Requests an airdrop of tokens to an account.
7158
7016
  *
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.
7017
+ * **Note**: Only available on devnet and testnet.
7161
7018
  *
7162
- * @param txCreationTime - Transaction creation time in milliseconds since Unix epoch
7019
+ * @param pubkey - Account to receive the airdrop
7020
+ * @param amount - Amount in kelvins (smallest unit)
7021
+ * @returns Transaction signature
7163
7022
  */
7164
- setTxCreationTime(txCreationTime) {
7165
- this.txCreationTime = txCreationTime;
7166
- return this;
7023
+ async requestAirdrop(pubkey, amount) {
7024
+ return await this.transactionClient.requestAirdrop(pubkey, amount);
7025
+ }
7026
+ };
7027
+
7028
+ // src/rpc/http-transport.ts
7029
+ var DEFAULT_CONFIG = {
7030
+ timeout: 3e4,
7031
+ // 30 seconds
7032
+ maxRetries: 3,
7033
+ retryBaseDelay: 1e3,
7034
+ // 1 second
7035
+ retryMaxDelay: 3e4,
7036
+ // 30 seconds
7037
+ headers: {}
7038
+ };
7039
+ var HttpTransport = class {
7040
+ url;
7041
+ config;
7042
+ constructor(url, config = {}) {
7043
+ this.url = url;
7044
+ this.config = { ...DEFAULT_CONFIG, ...config };
7167
7045
  }
7168
7046
  /**
7169
- * Add an instruction to the transaction.
7047
+ * Makes an HTTP request with automatic retry logic.
7170
7048
  *
7171
- * @param instruction - Instruction to add
7049
+ * Retries are attempted for network errors and server errors (5xx).
7050
+ * Uses exponential backoff between retry attempts.
7172
7051
  */
7173
- addInstruction(instruction) {
7174
- this.instructions.push(instruction);
7175
- return this;
7052
+ async request(body, requestDetails = {}) {
7053
+ let lastError;
7054
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
7055
+ try {
7056
+ return await this.makeRequest(body, requestDetails, attempt);
7057
+ } catch (error) {
7058
+ lastError = error;
7059
+ if (error instanceof RpcError && !error.retryable) {
7060
+ throw error;
7061
+ }
7062
+ if (attempt === this.config.maxRetries) {
7063
+ throw error;
7064
+ }
7065
+ const delay = calculateBackoff(
7066
+ attempt,
7067
+ this.config.retryBaseDelay,
7068
+ this.config.retryMaxDelay
7069
+ );
7070
+ await sleep(delay);
7071
+ }
7072
+ }
7073
+ throw lastError;
7176
7074
  }
7177
7075
  /**
7178
- * Add multiple instructions at once.
7179
- *
7180
- * @param instructions - Array of instructions to add
7076
+ * Make a single HTTP request with timeout
7181
7077
  */
7182
- addInstructions(instructions) {
7183
- this.instructions.push(...instructions);
7184
- return this;
7078
+ async makeRequest(body, requestDetails, attempt) {
7079
+ const controller = new AbortController();
7080
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
7081
+ try {
7082
+ const options = {
7083
+ method: "POST",
7084
+ headers: {
7085
+ "Content-Type": "application/json",
7086
+ ...this.config.headers
7087
+ },
7088
+ body,
7089
+ signal: controller.signal
7090
+ };
7091
+ const response = await fetch(this.url, options);
7092
+ if (!response.ok) {
7093
+ throw await this.handleHttpError(response, requestDetails, attempt);
7094
+ }
7095
+ const data = await response.json();
7096
+ return data;
7097
+ } catch (error) {
7098
+ if (error instanceof Error && error.name === "AbortError") {
7099
+ throw RpcError.requestTimeout(this.config.timeout, {
7100
+ ...requestDetails,
7101
+ url: this.url,
7102
+ attempts: attempt + 1
7103
+ });
7104
+ }
7105
+ if (error instanceof TypeError) {
7106
+ throw RpcError.networkError(error.message, {
7107
+ ...requestDetails,
7108
+ url: this.url,
7109
+ attempts: attempt + 1,
7110
+ cause: error.message
7111
+ });
7112
+ }
7113
+ if (error instanceof RpcError) {
7114
+ throw error;
7115
+ }
7116
+ throw RpcError.networkError("Unknown network error", {
7117
+ ...requestDetails,
7118
+ url: this.url,
7119
+ attempts: attempt + 1,
7120
+ cause: error instanceof Error ? error.message : String(error)
7121
+ });
7122
+ } finally {
7123
+ clearTimeout(timeoutId);
7124
+ }
7185
7125
  }
7186
7126
  /**
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
7193
- *
7194
- * @example
7195
- * ```typescript
7196
- * const tx = builder.build();
7197
- * const signedTx = tx.sign(keypair);
7198
- * ```
7127
+ * Handle HTTP error responses
7199
7128
  */
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
- );
7206
- }
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
- );
7212
- }
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
- );
7218
- }
7219
- if (this.instructions.length === 0) {
7220
- throw TransactionError.noInstructions();
7129
+ async handleHttpError(response, requestDetails, attempt) {
7130
+ const status = response.status;
7131
+ if (status === 429) {
7132
+ return RpcError.rateLimitExceeded({
7133
+ ...requestDetails,
7134
+ httpStatus: status,
7135
+ url: this.url,
7136
+ attempts: attempt + 1
7137
+ });
7221
7138
  }
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
7139
+ if (status >= 500) {
7140
+ return RpcError.networkError(`Server error: ${status}`, {
7141
+ ...requestDetails,
7142
+ httpStatus: status,
7143
+ url: this.url,
7144
+ attempts: attempt + 1
7234
7145
  });
7235
7146
  }
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
- );
7147
+ let message = `HTTP ${status}: ${response.statusText}`;
7148
+ try {
7149
+ const errorData = await response.json();
7150
+ if (errorData && typeof errorData === "object" && "message" in errorData) {
7151
+ message = String(errorData.message);
7245
7152
  }
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
- );
7253
- }
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
7153
+ } catch {
7154
+ }
7155
+ return new RpcError(
7156
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
7157
+ message,
7158
+ {
7159
+ ...requestDetails,
7160
+ httpStatus: status,
7161
+ url: this.url,
7162
+ attempts: attempt + 1
7163
+ },
7164
+ false
7165
+ // 4xx errors are not retryable
7269
7166
  );
7270
- return Transaction.fromMessage(message);
7167
+ }
7168
+ /**
7169
+ * Returns the configured RPC endpoint URL.
7170
+ */
7171
+ getUrl() {
7172
+ return this.url;
7271
7173
  }
7272
7174
  };
7273
7175
 
7176
+ // src/rpc/index.ts
7177
+ function createRialoClient(config) {
7178
+ const { chain: chain2, endpoint, transport } = config;
7179
+ const url = endpoint ?? chain2.rpcUrl;
7180
+ const httpTransport = new HttpTransport(url, transport);
7181
+ return new RialoClient(httpTransport, config.chain);
7182
+ }
7183
+ function getDefaultRialoClientConfig(network) {
7184
+ switch (network) {
7185
+ case "mainnet":
7186
+ return { chain: RIALO_MAINNET_CHAIN };
7187
+ case "devnet":
7188
+ return { chain: RIALO_DEVNET_CHAIN };
7189
+ case "testnet":
7190
+ return { chain: RIALO_TESTNET_CHAIN };
7191
+ case "localnet":
7192
+ return { chain: RIALO_LOCALNET_CHAIN };
7193
+ default:
7194
+ throw new RpcError(
7195
+ "INVALID_NETWORK" /* INVALID_NETWORK */,
7196
+ `Unknown network: ${network}`
7197
+ );
7198
+ }
7199
+ }
7200
+
7274
7201
  // src/signer/keypair-signer.ts
7275
7202
  var KeypairSigner = class {
7276
7203
  constructor(keypair) {
@@ -7291,9 +7218,6 @@ var KeypairSigner = class {
7291
7218
  };
7292
7219
  /*! Bundled license information:
7293
7220
 
7294
- @scure/base/index.js:
7295
- (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7296
-
7297
7221
  @noble/ed25519/index.js:
7298
7222
  (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
7299
7223
 
@@ -7301,15 +7225,16 @@ var KeypairSigner = class {
7301
7225
  @noble/hashes/utils.js:
7302
7226
  (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7303
7227
 
7228
+ @scure/base/index.js:
7229
+ (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
7230
+
7304
7231
  @scure/bip39/index.js:
7305
7232
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
7306
7233
  */
7307
7234
 
7308
7235
  exports.AccountMetaTable = AccountMetaTable;
7309
7236
  exports.BASE_DERIVATION_PATH = BASE_DERIVATION_PATH;
7310
- exports.BLOCKHASH_LENGTH = BLOCKHASH_LENGTH;
7311
7237
  exports.BaseRpcClient = BaseRpcClient;
7312
- exports.Blockhash = Blockhash;
7313
7238
  exports.CryptoError = CryptoError;
7314
7239
  exports.CryptoErrorCode = CryptoErrorCode;
7315
7240
  exports.DEFAULT_NUM_ACCOUNTS = DEFAULT_NUM_ACCOUNTS;
@@ -7322,6 +7247,10 @@ exports.Mnemonic = Mnemonic;
7322
7247
  exports.PUBLIC_KEY_LENGTH = PUBLIC_KEY_LENGTH;
7323
7248
  exports.PublicKey = PublicKey;
7324
7249
  exports.QueryRpcClient = QueryRpcClient;
7250
+ exports.RIALO_DEVNET_CHAIN = RIALO_DEVNET_CHAIN;
7251
+ exports.RIALO_LOCALNET_CHAIN = RIALO_LOCALNET_CHAIN;
7252
+ exports.RIALO_MAINNET_CHAIN = RIALO_MAINNET_CHAIN;
7253
+ exports.RIALO_TESTNET_CHAIN = RIALO_TESTNET_CHAIN;
7325
7254
  exports.RialoClient = RialoClient;
7326
7255
  exports.RialoError = RialoError;
7327
7256
  exports.RialoErrorType = RialoErrorType;
@@ -7347,6 +7276,7 @@ exports.createBorshInstruction = createBorshInstruction;
7347
7276
  exports.createRialoClient = createRialoClient;
7348
7277
  exports.encodeBorshData = encodeBorshData;
7349
7278
  exports.fromBase64 = fromBase64;
7279
+ exports.getDefaultRialoClientConfig = getDefaultRialoClientConfig;
7350
7280
  exports.getDevnetUrl = getDevnetUrl;
7351
7281
  exports.getLocalnetUrl = getLocalnetUrl;
7352
7282
  exports.getMainnetUrl = getMainnetUrl;