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