UNPKG

@shogun-sdk/money-legos

Version:

Shogun Money Legos: clients and types for quotes, memes, prices, balances, fees, validations, etc.

167 lines 5.42 kB
import { encode } from '@msgpack/msgpack'; import { ethers, getBytes, keccak256 } from 'ethers'; const phantomDomain = { name: 'Exchange', version: '1', chainId: 1337, verifyingContract: '0x0000000000000000000000000000000000000000', }; const agentTypes = { Agent: [ { name: 'source', type: 'string' }, { name: 'connectionId', type: 'bytes32' }, ], }; export function orderTypeToWire(orderType) { if (orderType.limit) { return { limit: orderType.limit }; } else if (orderType.trigger) { return { trigger: { isMarket: orderType.trigger.isMarket, triggerPx: floatToWire(Number(orderType.trigger.triggerPx)), tpsl: orderType.trigger.tpsl, }, }; } throw new Error('Invalid order type'); } function addressToBytes(address) { return getBytes(address); } function actionHash(action, vaultAddress, nonce) { const msgPackBytes = encode(action); const additionalBytesLength = vaultAddress === null ? 9 : 29; const data = new Uint8Array(msgPackBytes.length + additionalBytesLength); data.set(msgPackBytes); const view = new DataView(data.buffer); view.setBigUint64(msgPackBytes.length, BigInt(nonce), false); if (vaultAddress === null) { view.setUint8(msgPackBytes.length + 8, 0); } else { view.setUint8(msgPackBytes.length + 8, 1); data.set(addressToBytes(vaultAddress), msgPackBytes.length + 9); } return keccak256(data); } function constructPhantomAgent(hash) { return { source: 'a', connectionId: hash }; } export async function signL1Action(wallet, action, activePool, nonce) { const hash = actionHash(action, activePool, nonce); const phantomAgent = constructPhantomAgent(hash); const data = { domain: phantomDomain, types: agentTypes, primaryType: 'Agent', message: phantomAgent, }; return signInner(wallet, data); } export async function signUserSignedAction(wallet, action, payloadTypes, primaryType) { action.signatureChainId = '0x66eee'; action.hyperliquidChain = 'Mainnet'; const data = { domain: { name: 'HyperliquidSignTransaction', version: '1', chainId: 421614, verifyingContract: '0x0000000000000000000000000000000000000000', }, types: { [primaryType]: payloadTypes, }, primaryType: primaryType, message: action, }; return signInner(wallet, data); } export async function signUsdTransferAction(wallet, action) { return signUserSignedAction(wallet, action, [ { name: 'hyperliquidChain', type: 'string' }, { name: 'destination', type: 'string' }, { name: 'amount', type: 'string' }, { name: 'time', type: 'uint64' }, ], 'HyperliquidTransaction:UsdSend'); } export async function signWithdrawFromBridgeAction(wallet, action) { return signUserSignedAction(wallet, action, [ { name: 'hyperliquidChain', type: 'string' }, { name: 'destination', type: 'string' }, { name: 'amount', type: 'string' }, { name: 'time', type: 'uint64' }, ], 'HyperliquidTransaction:Withdraw'); } export async function signAgent(wallet, action) { return signUserSignedAction(wallet, action, [ { name: 'hyperliquidChain', type: 'string' }, { name: 'agentAddress', type: 'address' }, { name: 'agentName', type: 'string' }, { name: 'nonce', type: 'uint64' }, ], 'HyperliquidTransaction:ApproveAgent'); } async function signInner(wallet, data) { const signature = await wallet.signTypedData(data.domain, data.types, data.message); return splitSig(signature); } function splitSig(sig) { const { r, s, v } = ethers.Signature.from(sig); return { r, s, v }; } export function floatToWire(x) { const rounded = x.toFixed(8); if (Math.abs(parseFloat(rounded) - x) >= 1e-12) { throw new Error(`floatToWire causes rounding: ${x}`); } let normalized = rounded.replace(/\.?0+$/, ''); if (normalized === '-0') normalized = '0'; return normalized; } export function floatToIntForHashing(x) { return floatToInt(x, 8); } export function floatToUsdInt(x) { return floatToInt(x, 6); } function floatToInt(x, power) { const withDecimals = x * Math.pow(10, power); if (Math.abs(Math.round(withDecimals) - withDecimals) >= 1e-3) { throw new Error(`floatToInt causes rounding: ${x}`); } return Math.round(withDecimals); } export function getTimestampMs() { return Date.now(); } export function orderToWire(order, asset) { const orderWire = { a: asset, b: order.is_buy, p: floatToWire(order.limit_px), s: floatToWire(order.sz), r: order.reduce_only, t: orderTypeToWire(order.order_type), }; if (order.cloid !== undefined) { orderWire.c = order.cloid; } return orderWire; } export function orderWireToAction(orders, grouping = 'na', builder) { return { type: 'order', orders: orders, grouping: grouping, ...(builder !== undefined ? { builder: builder } : {}), }; } export function cancelOrderToAction(cancelRequest) { return { type: 'cancel', cancels: [cancelRequest], }; } //# sourceMappingURL=signing.js.map