Skip to content

Instantly share code, notes, and snippets.

@JonathanGawrych
Last active March 18, 2024 04:06
Show Gist options
  • Select an option

  • Save JonathanGawrych/6b79eef79ae3a84120bc137cdb3e528b to your computer and use it in GitHub Desktop.

Select an option

Save JonathanGawrych/6b79eef79ae3a84120bc137cdb3e528b to your computer and use it in GitHub Desktop.
Userscript to automatically fill out the HSA Partial Transfer form for Health Equity to Fidelity
// ==UserScript==
// @name Fill Out HSA Transfer
// @match https://member.my.healthequity.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
let toTransfer = null;
let initedForm = false;
function tryFillOutBalance () {
if (!initedForm) {
return;
}
if (toTransfer == null) {
return;
}
const field = document.querySelector('#partialTransferAmount');
field.value = toTransfer;
field.dispatchEvent(new Event('input'));
}
// Patch XHR to steal the access token to get our balance
XMLHttpRequest.prototype.open = ((oldFn) => {
return function open(...args) {
const listener = async () => {
if (this.readyState !== XMLHttpRequest.DONE) {
return;
}
if (this.status !== 200) {
return;
}
if (!this.responseText.includes('access_token')) {
return;
}
const accessToken = JSON.parse(this.responseText).access_token;
XMLHttpRequest.prototype.open = oldFn;
const response = await fetch('https://api.my.healthequity.com/apps/memberaccountaggregationbefe/balanceBoosterDetail', {
'headers': {
'Accept': 'application/json',
'authorization': `Bearer ${accessToken}`
},
});
const json = await response.json();
toTransfer = json.availableToSpend - 25;
tryFillOutBalance();
};
this.addEventListener("readystatechange", listener);
return oldFn.apply(this, args);
};
})(XMLHttpRequest.prototype.open);
const myFont = new FontFace('Cedarville', 'url(https://fonts.gstatic.com/s/cedarvillecursive/v12/yYL00g_a2veiudhUmxjo5VKkoqA-B_nuIrpw4cNOTw.woff2) format("woff2")');
const myFontLoaded = myFont.load();
// Wait until the form is loaded
const formObserver = new MutationObserver(function (mutations, formObserver) {
if (document.querySelector('spas-hsa-transfer-page') === null) {
return;
}
initedForm = true;
formObserver.disconnect();
tryFillOutBalance();
document.querySelector('#institutionName').value = 'Fidelity';
document.querySelector('#institutionName').dispatchEvent(new Event('input'));
document.querySelector('#accountNumber').value = '[Account Number]';
document.querySelector('#accountNumber').dispatchEvent(new Event('input'));
document.querySelector('#streetAddress').value = 'PO Box 770001';
document.querySelector('#streetAddress').dispatchEvent(new Event('input'));
document.querySelector('#city').value = 'Cincinnati';
document.querySelector('#city').dispatchEvent(new Event('input'));
document.querySelector('#state').selectedIndex = 40; // 'OH'
document.querySelector('#state').dispatchEvent(new Event('change'));
document.querySelector('#zip').value = '45277-0036';
document.querySelector('#zip').dispatchEvent(new Event('input'));
document.querySelector('#certifyRequest').checked = 'checked';
document.querySelector('#certifyRequest').dispatchEvent(new Event('change'));
});
// start observing
formObserver.observe(document, {
childList: true,
subtree: true
});
// Wait until we get to the next page and the signature loads
const signatureObserver = new MutationObserver(function (mutations, signatureObserver) {
const canvas = document.querySelector('canvas');
if (canvas === null) {
return;
}
signatureObserver.disconnect();
myFontLoaded.then((font) => {
document.fonts.add(font);
const ctx = canvas.getContext("2d");
ctx.fillStyle = '#009';
ctx.font = '32px Cedarville';
ctx.fillText('Jonathan Gawrych', 90, 50);
const boundingBox = canvas.getBoundingClientRect();
canvas.dispatchEvent(new MouseEvent('pointerdown', {
clientX: boundingBox.left,
clientY: boundingBox.top
}));
});
});
signatureObserver.observe(document, {
childList: true,
subtree: true
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment