@mysten/sui
Version:
Sui TypeScript API
1 lines • 4.36 kB
Source Map (JSON)
{"version":3,"file":"coin-reservation.mjs","names":["bcs"],"sources":["../../src/utils/coin-reservation.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase58, fromHex, toBase58, toHex } from '@mysten/bcs';\nimport { parse } from 'valibot';\n\nimport { bcs, TypeTagSerializer } from '../bcs/index.js';\nimport { ObjectRefSchema } from '../transactions/data/internal.js';\nimport { deriveDynamicFieldID } from './dynamic-fields.js';\nimport { normalizeSuiAddress } from './index.js';\n\nconst SUI_ACCUMULATOR_ROOT_OBJECT_ID = normalizeSuiAddress('0xacc');\nconst ACCUMULATOR_KEY_TYPE_TAG = TypeTagSerializer.parseFromStr(\n\t'0x2::accumulator::Key<0x2::balance::Balance<0x2::sui::SUI>>',\n);\n\nexport const COIN_RESERVATION_MAGIC = new Uint8Array([\n\t0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,\n\t0xac, 0xac, 0xac, 0xac,\n]);\n\nexport function isCoinReservationDigest(digestBase58: string): boolean {\n\tconst digestBytes = fromBase58(digestBase58);\n\tconst last20Bytes = digestBytes.slice(12, 32);\n\treturn last20Bytes.every((byte, i) => byte === COIN_RESERVATION_MAGIC[i]);\n}\n\nexport function parseCoinReservationBalance(digestBase58: string): bigint {\n\tconst digestBytes = fromBase58(digestBase58);\n\tconst view = new DataView(digestBytes.buffer, digestBytes.byteOffset, digestBytes.byteLength);\n\treturn view.getBigUint64(0, true);\n}\n\n/**\n * Derives the accumulator dynamic field object ID for the given owner,\n * then XORs it with the chain identifier bytes to produce the objectId\n * for the coin reservation ref.\n */\nfunction deriveReservationObjectId(owner: string, chainIdentifier: string): string {\n\tconst keyBcs = bcs.Address.serialize(owner).toBytes();\n\tconst accumulatorId = deriveDynamicFieldID(\n\t\tSUI_ACCUMULATOR_ROOT_OBJECT_ID,\n\t\tACCUMULATOR_KEY_TYPE_TAG,\n\t\tkeyBcs,\n\t);\n\n\t// XOR the accumulator object ID bytes with the chain identifier bytes\n\tconst accBytes = fromHex(accumulatorId.slice(2));\n\tconst chainBytes = fromBase58(chainIdentifier);\n\tif (chainBytes.length !== 32) {\n\t\tthrow new Error(`Invalid chain identifier length: expected 32 bytes, got ${chainBytes.length}`);\n\t}\n\tconst xored = new Uint8Array(32);\n\tfor (let i = 0; i < 32; i++) {\n\t\txored[i] = accBytes[i] ^ chainBytes[i];\n\t}\n\treturn `0x${toHex(xored)}`;\n}\n\nexport function createCoinReservationRef(\n\treservedBalance: bigint,\n\towner: string,\n\tchainIdentifier: string,\n\tepoch: string,\n) {\n\tconst digestBytes = new Uint8Array(32);\n\tconst view = new DataView(digestBytes.buffer);\n\t// Bytes 0-7: reserved balance as LE u64\n\tview.setBigUint64(0, reservedBalance, true);\n\t// Bytes 8-11: epoch_id as LE u32\n\tconst epochNum = Number(epoch);\n\tif (!Number.isSafeInteger(epochNum) || epochNum < 0 || epochNum > 0xffffffff) {\n\t\tthrow new Error(`Epoch ${epoch} out of u32 range for coin reservation digest`);\n\t}\n\tview.setUint32(8, epochNum, true);\n\t// Bytes 12-31: magic bytes\n\tdigestBytes.set(COIN_RESERVATION_MAGIC, 12);\n\n\treturn parse(ObjectRefSchema, {\n\t\tobjectId: deriveReservationObjectId(owner, chainIdentifier),\n\t\tversion: '0',\n\t\tdigest: toBase58(digestBytes),\n\t});\n}\n"],"mappings":";;;;;;;;;AAWA,MAAM,iCAAiC,oBAAoB,QAAQ;AACnE,MAAM,2BAA2B,kBAAkB,aAClD,8DACA;AAED,MAAa,yBAAyB,IAAI,WAAW;CACpD;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAC1F;CAAM;CAAM;CAAM;CAClB,CAAC;AAEF,SAAgB,wBAAwB,cAA+B;AAGtE,QAFoB,WAAW,aAAa,CACZ,MAAM,IAAI,GAAG,CAC1B,OAAO,MAAM,MAAM,SAAS,uBAAuB,GAAG;;;;;;;AAc1E,SAAS,0BAA0B,OAAe,iBAAiC;CASlF,MAAM,WAAW,QAPK,qBACrB,gCACA,0BAHcA,OAAI,QAAQ,UAAU,MAAM,CAAC,SAAS,CAKpD,CAGsC,MAAM,EAAE,CAAC;CAChD,MAAM,aAAa,WAAW,gBAAgB;AAC9C,KAAI,WAAW,WAAW,GACzB,OAAM,IAAI,MAAM,2DAA2D,WAAW,SAAS;CAEhG,MAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IACvB,OAAM,KAAK,SAAS,KAAK,WAAW;AAErC,QAAO,KAAK,MAAM,MAAM;;AAGzB,SAAgB,yBACf,iBACA,OACA,iBACA,OACC;CACD,MAAM,cAAc,IAAI,WAAW,GAAG;CACtC,MAAM,OAAO,IAAI,SAAS,YAAY,OAAO;AAE7C,MAAK,aAAa,GAAG,iBAAiB,KAAK;CAE3C,MAAM,WAAW,OAAO,MAAM;AAC9B,KAAI,CAAC,OAAO,cAAc,SAAS,IAAI,WAAW,KAAK,WAAW,WACjE,OAAM,IAAI,MAAM,SAAS,MAAM,+CAA+C;AAE/E,MAAK,UAAU,GAAG,UAAU,KAAK;AAEjC,aAAY,IAAI,wBAAwB,GAAG;AAE3C,QAAO,MAAM,iBAAiB;EAC7B,UAAU,0BAA0B,OAAO,gBAAgB;EAC3D,SAAS;EACT,QAAQ,SAAS,YAAY;EAC7B,CAAC"}