87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
const https = require('https');
|
|
const { ethers } = require('ethers');
|
|
const { encode } = require('@msgpack/msgpack');
|
|
|
|
const host = "api.hyperliquid-testnet.xyz";
|
|
const privKey = "0xcb4e58b6c0921fd4aa8e49cd8a9f06b98b4e6b9cdf7c60c63ba1416856bb0b2a";
|
|
const wallet = new ethers.Wallet(privKey);
|
|
|
|
async function api(method, path, payload) {
|
|
return new Promise((resolve, reject) => {
|
|
const data = JSON.stringify(payload);
|
|
const opts = { hostname: host, path, method, headers: { 'Content-Type': 'application/json' } };
|
|
const req = https.request(opts, res => {
|
|
let body = '';
|
|
res.on('data', c => body += c);
|
|
res.on('end', () => { try { resolve(JSON.parse(body)); } catch(e) { resolve(body); } });
|
|
});
|
|
req.on('error', reject);
|
|
req.write(data); req.end();
|
|
});
|
|
}
|
|
|
|
async function sign(action) {
|
|
const nonce = Date.now() * 1000000 + Math.floor(Math.random() * 1000000);
|
|
|
|
// Normalize
|
|
function normalize(obj) {
|
|
if (!obj || typeof obj !== 'object') return;
|
|
if (Array.isArray(obj)) { for (const i of obj) normalize(i); }
|
|
else { for (const k of Object.keys(obj)) {
|
|
if ((k === 'p' || k === 's') && typeof obj[k] === 'string')
|
|
obj[k] = obj[k].replace(/\.?0+$/, '').replace(/^-0$/, '0');
|
|
else normalize(obj[k]);
|
|
}}
|
|
}
|
|
const act = JSON.parse(JSON.stringify(action));
|
|
normalize(act);
|
|
|
|
const msgBytes = encode(act);
|
|
const buf = new Uint8Array(msgBytes.length + 8 + 1);
|
|
buf.set(msgBytes, 0);
|
|
new DataView(buf.buffer).setBigUint64(msgBytes.length, BigInt(nonce), false);
|
|
buf[msgBytes.length + 8] = 0;
|
|
const hash = ethers.keccak256(buf);
|
|
|
|
const sig = ethers.Signature.from(await wallet.signTypedData(
|
|
{ name: 'Exchange', version: '1', chainId: 1337, verifyingContract: '0x0000000000000000000000000000000000000000' },
|
|
{ Agent: [{ name: 'source', type: 'string' }, { name: 'connectionId', type: 'bytes32' }] },
|
|
{ source: 'b', connectionId: hash }
|
|
));
|
|
|
|
return { action, nonce, signature: { r: sig.r, s: sig.s, v: sig.v } };
|
|
}
|
|
|
|
async function main() {
|
|
// Get meta to find asset index
|
|
const meta = await api('POST', '/info', { type: 'meta' });
|
|
const btcIdx = meta.universe.findIndex(u => u.name === 'BTC');
|
|
console.log(`BTC asset index: ${btcIdx}`);
|
|
|
|
// Get mid price for BTC
|
|
const mids = await api('POST', '/info', { type: 'allMids' });
|
|
const btcMid = parseFloat(mids['BTC']);
|
|
console.log(`BTC mid: ${btcMid}`);
|
|
|
|
// Place a small market buy order (IOC, high limit price)
|
|
const orderAction = {
|
|
type: 'order',
|
|
orders: [{
|
|
a: btcIdx,
|
|
b: true, // buy
|
|
p: (btcMid * 2).toFixed(0),
|
|
s: '0.001',
|
|
r: false,
|
|
t: { limit: { tif: 'Ioc' } }
|
|
}],
|
|
grouping: 'na'
|
|
};
|
|
|
|
const signed = await sign(orderAction);
|
|
console.log('\nSending order...');
|
|
const result = await api('POST', '/exchange', signed);
|
|
console.log(JSON.stringify(result, null, 2));
|
|
}
|
|
|
|
main().catch(console.error);
|