@firefly-exchange/library-sui
Version:
Sui library housing helper methods, classes to interact with Bluefin protocol(s) deployed on Sui
190 lines (189 loc) • 8.77 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarginingEngineSimulator = void 0;
const utils_1 = require("@noble/hashes/utils");
const bcs_1 = require("./bcs");
const blake2b_1 = require("@noble/hashes/blake2b");
const deployment_parser_1 = require("./deployment-parser");
const library_1 = require("../../library");
const _ = __importStar(require("lodash"));
class MarginingEngineSimulator {
constructor(suiClient, deployment) {
/// 64 length blake2b hash of all tx processed till date
this.sequenceHash = "0000000000000000000000000000000000000000000000000000000000000000";
this.suiClient = suiClient;
this.parser = new deployment_parser_1.DeploymentParser(deployment);
}
/**
* Initializes the sequencer by fetching the on-chain sequence hash
*/
async init() {
const details = await this.suiClient.getObject({
id: this.parser.getInternalDataStore(),
options: { showContent: true }
});
this.sequenceHash = (0, utils_1.bytesToHex)(new Uint8Array(details.data.content.fields.sequence_hash));
}
/**
* Creates sequence hash for a transaction
* @param Serialized payload to be used for sequence hash computation
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
computeSequenceHash(payload, update = true, sequenceHash) {
const newSequenceHash = (0, utils_1.bytesToHex)((0, blake2b_1.blake2b)((0, library_1.hexToBuffer)(`${sequenceHash || this.sequenceHash}${payload}`), {
dkLen: 32
}));
if (update) {
this.sequenceHash = newSequenceHash;
}
return newSequenceHash;
}
/**
* Creates sequence hash for a deposit transaction
* @param event AssetBankDeposit event
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
depositToInternalBank(event, update = true) {
const serialized = bcs_1.BCSUtils.getSerializedDataHex({ ...event, tainted: false }, bcs_1.Deposit);
return this.computeSequenceHash(serialized, update);
}
/**
* Creates sequence hash for a deposit transaction
* @param event AssetBankDeposit event
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
removeTaintedAsset(event, update = true) {
const serialized = bcs_1.BCSUtils.getSerializedDataHex({ ...event, tainted: true }, bcs_1.Deposit);
return this.computeSequenceHash(serialized, update);
}
/**
* Creates sequence hash for sync perpetual state tx
* @param event Event for any perpetual attribute update
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
syncPerpetual(event, update = true) {
let perpetual = { ...event.perpetual };
// set oracle price to zero during serialization as on-chain
// we bcs serialize the perpetual struct stored in EDS which has the oracle price zero
perpetual.oraclePrice = 0;
perpetual.funding = {
timestamp: 0,
rate: { value: 0, sign: true }
};
// the incoming event may have fields in snake_case
perpetual = _.mapKeys(perpetual, (_v, k) => _.camelCase(k));
const serialized = bcs_1.BCSUtils.getSerializedDataHex(perpetual, bcs_1.PerpetualUpdate);
return this.computeSequenceHash(serialized, update);
}
/**
* Creates sequence hash for sync support asset tx
* @param event Event for margin bank creation
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
syncSupportedAsset(event, update = true) {
const serialized = bcs_1.BCSUtils.getSerializedDataHex(event.asset, bcs_1.AssetSupported);
return this.computeSequenceHash(serialized, update);
}
/**
* Creates sequence hash for trade tx
* @param makerSignature The signature of the maker order
* @param takerSignature The signature of the taker order
* @param quantity The quantity of the trade bring filled
* @param timestamp Timestamp in ms (this is sent to chain as well)
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @param sequenceHash (optional) sequence hash to be used to compute the next sequence hash
* @returns the new sequence hash
*/
performTrade(makerSignature, takerSignature, quantity, timestamp, update = true, sequenceHash) {
const trade = {
makerSignature: (0, library_1.hexStrToUint8)((0, library_1.base64ToHex)(makerSignature)),
takerSignature: (0, library_1.hexStrToUint8)((0, library_1.base64ToHex)(takerSignature)),
quantity,
timestamp
};
const serialized = bcs_1.BCSUtils.getSerializedDataHex(trade, bcs_1.TradeData);
return this.computeSequenceHash(serialized, update, sequenceHash);
}
overwriteUserPosition(ids, account, position, timestamp, update = true, sequenceHash) {
const overwriteUserPositionData = {
ids,
account,
perpetual: position.perpetual,
size: position.size,
average_entry_price: position.average_entry_price,
leverage: position.leverage,
margin: position.margin,
is_long: position.is_long,
is_isolated: position.is_isolated,
pending_funding_payment: position.pending_funding_payment,
last_funding_timestamp: position.funding.timestamp,
last_funding_rate_value: position.funding.rate.value,
last_funding_rate_sign: position.funding.rate.sign,
timestamp
};
const serialized = bcs_1.BCSUtils.getSerializedDataHex(overwriteUserPositionData, bcs_1.OverwriteUserPosition);
return this.computeSequenceHash(serialized, update, sequenceHash);
}
overwriteUserAssets(ids, account, amount, timestamp, update = true, sequenceHash) {
const overwriteUserAssetsData = {
ids,
account,
amount,
timestamp
};
const serialized = bcs_1.BCSUtils.getSerializedDataHex(overwriteUserAssetsData, bcs_1.OverwriteUserAssets);
return this.computeSequenceHash(serialized, update, sequenceHash);
}
/**
* Creates sequence hash for sync support asset tx
* @param event Event for margin bank creation
* @param update (optional) if true will update the stored sequence hash else will just return the new hash
* @returns the new sequence hash
*/
syncOperator(event, update = true) {
const serialized = bcs_1.BCSUtils.getSerializedDataHex({
operatorType: event.operator_type,
previousOperator: event.previous_operator,
newOperator: event.new_operator
}, bcs_1.SyncOperator);
return this.computeSequenceHash(serialized, update);
}
/// returns current sequence hash
getSequenceHash() {
return this.sequenceHash;
}
/// sets the sequence hash to the provided one
setSequenceHash(sequenceHash) {
this.sequenceHash = sequenceHash;
}
}
exports.MarginingEngineSimulator = MarginingEngineSimulator;
;