Created
October 1, 2023 10:51
-
-
Save mdsohelmia/a4d8c5b011391f0a4f4c97246650a60b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ec = new TextEncoder(); | |
const algorithm = { name: "HMAC", hash: "SHA-256" }; | |
// generates a signature for the given data using the given key | |
async function generateHmacKey(secret) { | |
const { subtle } = globalThis.crypto; | |
return subtle.importKey( | |
"raw", | |
typeof secret === "string" ? ec.encode(secret) : secret, | |
algorithm, | |
false, | |
["sign"] | |
); | |
} | |
async function hash(key, data) { | |
const { subtle } = globalThis.crypto; | |
return subtle.sign(algorithm, await generateHmacKey(key), ec.encode(data)); | |
} | |
function arrayBufferToHexString(arrayBuffer) { | |
const byteArray = new Uint8Array(arrayBuffer); | |
let hexString = ""; | |
for (let i = 0; i < byteArray.length; i++) { | |
hexString += byteArray[i].toString(16).padStart(2, "0"); | |
} | |
return hexString; | |
} | |
const nonce = generateNonce(); | |
const date = new Date(); | |
const apiSecret = "DEYt52UW00siPrqeaTIaSKL8o7cMhUil"; | |
const requestData = { | |
method: "GET", | |
uri: "/example", | |
xDate: ISO8601DateFormat(date), | |
nonce: generateNonce(), | |
requestBody: '{"data": "test"}', | |
}; | |
async function createAuthorizeToken(secret, data) { | |
const signature = await hash(secret, data); | |
const hexSignature = arrayBufferToHexString(signature); | |
return hexSignature; | |
} | |
// Construct the signing string | |
const signingString = `${requestData.method}\n${requestData.uri}\n${requestData.timestamp}\n${requestData.nonce}\n${requestData.requestBody}`; | |
async function performAPICall() { | |
const signature = await createAuthorizeToken(apiSecret, signingString); | |
const headers = { | |
Authorization: `${apiSecret}:${signature}`, | |
"Content-Type": "application/json", | |
"X-Date": requestData.xDate, | |
"X-Nonce": requestData.nonce, | |
} | |
// xhr request | |
const xhr = new XMLHttpRequest(); | |
xhr.open(requestData.method, `https://api.sandbox.gemini.com${requestData.uri}`, true); | |
xhr.setRequestHeader("Authorization", headers.Authorization); | |
xhr.setRequestHeader("Content-Type", headers["Content-Type"]); | |
xhr.setRequestHeader("X-Date", headers["X-Date"]); | |
xhr.setRequestHeader("X-Nonce", headers["X-Nonce"]); | |
xhr.send(requestData.requestBody); | |
xhr.onreadystatechange = function () { | |
if (xhr.readyState === 4) { | |
console.log(xhr.status); | |
console.log(xhr.responseText); | |
} | |
} | |
} | |
performAPICall(); | |
// Authorization Header Format | |
// Authorization:${apiSecret}:${signature} | |
//Content-Type: application/json | |
// X-Date: ${date} | |
// X-Nonce: ${nonce} | |
function generateNonce() { | |
const timestamp = Date.now(); // in milliseconds | |
const randomDigits = Math.floor(Math.random() * 1000); | |
const nonce = `${timestamp}${randomDigits}`; | |
return nonce; | |
} | |
function ISO8601DateFormat(date) { | |
const year = date.getFullYear(); | |
const month = String(date.getMonth() + 1).padStart(2, "0"); // Months are 0-based, so add 1 and pad with 0 if necessary | |
const day = String(date.getDate()).padStart(2, "0"); | |
const hours = String(date.getHours()).padStart(2, "0"); | |
const minutes = String(date.getMinutes()).padStart(2, "0"); | |
const seconds = String(date.getSeconds()).padStart(2, "0"); | |
return `${year}${month}${day}T${hours}${minutes}${seconds}Z`; | |
} | |
console.log(ISO8601DateFormat(date)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment