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