@mysten/sui
Version:
Sui TypeScript API
67 lines (65 loc) • 2.45 kB
JavaScript
import { normalizeSuiAddress } from "./sui-types.mjs";
import { TypeTagSerializer } from "../bcs/type-tag-serializer.mjs";
import { bcs as suiBcs } from "../bcs/index.mjs";
import { deriveDynamicFieldID } from "./dynamic-fields.mjs";
import { ObjectRefSchema } from "../transactions/data/internal.mjs";
import { fromBase58, fromHex, toBase58, toHex } from "@mysten/bcs";
import { parse } from "valibot";
//#region src/utils/coin-reservation.ts
const SUI_ACCUMULATOR_ROOT_OBJECT_ID = normalizeSuiAddress("0xacc");
const ACCUMULATOR_KEY_TYPE_TAG = TypeTagSerializer.parseFromStr("0x2::accumulator::Key<0x2::balance::Balance<0x2::sui::SUI>>");
const COIN_RESERVATION_MAGIC = new Uint8Array([
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172,
172
]);
function isCoinReservationDigest(digestBase58) {
return fromBase58(digestBase58).slice(12, 32).every((byte, i) => byte === COIN_RESERVATION_MAGIC[i]);
}
/**
* Derives the accumulator dynamic field object ID for the given owner,
* then XORs it with the chain identifier bytes to produce the objectId
* for the coin reservation ref.
*/
function deriveReservationObjectId(owner, chainIdentifier) {
const accBytes = fromHex(deriveDynamicFieldID(SUI_ACCUMULATOR_ROOT_OBJECT_ID, ACCUMULATOR_KEY_TYPE_TAG, suiBcs.Address.serialize(owner).toBytes()).slice(2));
const chainBytes = fromBase58(chainIdentifier);
if (chainBytes.length !== 32) throw new Error(`Invalid chain identifier length: expected 32 bytes, got ${chainBytes.length}`);
const xored = new Uint8Array(32);
for (let i = 0; i < 32; i++) xored[i] = accBytes[i] ^ chainBytes[i];
return `0x${toHex(xored)}`;
}
function createCoinReservationRef(reservedBalance, owner, chainIdentifier, epoch) {
const digestBytes = new Uint8Array(32);
const view = new DataView(digestBytes.buffer);
view.setBigUint64(0, reservedBalance, true);
const epochNum = Number(epoch);
if (!Number.isSafeInteger(epochNum) || epochNum < 0 || epochNum > 4294967295) throw new Error(`Epoch ${epoch} out of u32 range for coin reservation digest`);
view.setUint32(8, epochNum, true);
digestBytes.set(COIN_RESERVATION_MAGIC, 12);
return parse(ObjectRefSchema, {
objectId: deriveReservationObjectId(owner, chainIdentifier),
version: "0",
digest: toBase58(digestBytes)
});
}
//#endregion
export { createCoinReservationRef, isCoinReservationDigest };
//# sourceMappingURL=coin-reservation.mjs.map