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