UNPKG

@debridge-finance/solana-utils

Version:

Common utils package to power communication with Solana contracts at deBridge

140 lines 5.89 kB
import { Buffer } from "buffer"; import { PublicKey } from "@solana/web3.js"; import BN from "bn.js"; import { keccak256 as rawKeccak256 } from "js-sha3"; import { hexToBuffer } from "./helpers"; import { isBuffer, } from "./interfaces"; import { DEPLOY_INFO_PREFIX, SUBMISSION_PREFIX } from "./constants"; import { solidityPack } from "./solidityPack"; export const keccak256 = (data) => `0x${rawKeccak256(data)}`; export const solidityKeccak256 = (types, values) => { const packed = solidityPack(types, values); return keccak256(packed); }; export function denormalizeAmount(amount, denominator) { const denominatorBN = new BN(Math.pow(10, denominator)); return amount.mul(denominatorBN).toArrayLike(Buffer, "be", 32); } export function normalizeChainId(chainId) { return hexToBuffer(`0x${isBuffer(chainId) ? chainId.toString("hex") : new BN(chainId).toString(16)}`, 32); } /** * Hashes deploy info * @param params {@link HashDeployInfoParams} * @returns keccak256 of deployInfo structure */ export function hashDeployInfo(params) { const nameHash = solidityKeccak256(["string"], [params.tokenName]); const symbolHash = solidityKeccak256(["string"], [params.tokenSymbol]); const deployInfoHash = solidityKeccak256(["uint256", "uint256", "uint256", "uint256", "uint8"], [ DEPLOY_INFO_PREFIX, params.debridgeId, nameHash, symbolHash, params.decimals, ]); return deployInfoHash; } /** * Returns bridgeid hash * @param nativeChainId chain id where token originates * @param nativeTokenAddress address of token in native chain in format "0x<HEX STRING>" * @returns bridge id in deBridge network */ export function hashDebridgeId(nativeChainId, nativeTokenAddress) { const chainIdBuffer = normalizeChainId(nativeChainId); const bridgeId = solidityKeccak256(["uint256", "bytes"], [chainIdBuffer, nativeTokenAddress]); return bridgeId; } export function hashExternalCallBytes(data) { if (data === undefined || (data === null || data === void 0 ? void 0 : data.length) === 0) { // precomputed "empty" hash return Buffer.from([ 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112, ]); } return hexToBuffer(solidityKeccak256(["bytes"], [data ? data : Buffer.from([])]), 32); } function isSendHashedFlagSet(packedFlags) { const SEND_HASHED_DATA_FLAG_BIT_NUMBER = BigInt(3); const result = (packedFlags >> SEND_HASHED_DATA_FLAG_BIT_NUMBER) & BigInt(1); return result === BigInt(1); } function getShortcutFromAutoParams(params) { var _a, _b, _c; const shortcut = (_a = params.autoParams) === null || _a === void 0 ? void 0 : _a.shortcut; if (shortcut) { return isBuffer(shortcut) ? shortcut : hexToBuffer(shortcut); } else { const flags = BigInt(new BN(((_b = params.autoParams) === null || _b === void 0 ? void 0 : _b.flags) || 0).toNumber()); const data = (_c = params.autoParams) === null || _c === void 0 ? void 0 : _c.data; if (!data) return hashExternalCallBytes(data); if (isSendHashedFlagSet(flags)) { const result = isBuffer(data) ? data : hexToBuffer(data); if (result.length !== 32) { throw new Error(`Incorrect autoParams.data length for SEND_HASHED_DATA_FLAG`); } return result; } return hashExternalCallBytes(data); } } /** * Hashes submission for provided data * @param params data to hash * @returns submissionId from provided params */ export function hashSubmissionIdRaw(params) { var _a, _b; let packParams = [ "uint256", // submission prefix "bytes32", // bridge_id "uint256", // source_chain_id "uint256", // target_chain_id "uint256", // amount "bytes", // receiver "uint256", // nonce ]; const receiver = isBuffer(params.receiver) ? params.receiver : typeof params.receiver === "string" ? params.receiver.startsWith("0x") ? hexToBuffer(params.receiver) : new PublicKey(params.receiver).toBuffer() : new PublicKey(params.receiver).toBuffer(); let packData = [ SUBMISSION_PREFIX, params.debridgeId, // bridge_id normalizeChainId(params.sourceChainId), // source_chain_id normalizeChainId(params.targetChainId), // target_chain_id new BN(params.amount).toArray("be", 32), // amount receiver, // receiver params.nonce, // nonce ]; if (params === null || params === void 0 ? void 0 : params.autoParams) { packParams = packParams.concat([ "uint256", // execution fee "uint256", // flag "bytes32", // fallback hash "uint256", // ext call data hash "uint256", // native sender hash ]); const shortcut = getShortcutFromAutoParams(params); const fallback = params.autoParams.fallbackAddress.startsWith("0x") ? hexToBuffer(params.autoParams.fallbackAddress) : new PublicKey(params.autoParams.fallbackAddress).toBuffer(); packData = packData.concat([ new BN(((_a = params === null || params === void 0 ? void 0 : params.autoParams) === null || _a === void 0 ? void 0 : _a.executionFee) || 0).toArray("be", 32), new BN(((_b = params.autoParams) === null || _b === void 0 ? void 0 : _b.flags) || 0).toArray("be", 32), hashExternalCallBytes(fallback), shortcut, hashExternalCallBytes(params.autoParams.nativeSender), ]); } const submissionIdHash = solidityKeccak256(packParams, packData); return submissionIdHash; } //# sourceMappingURL=crypto.js.map