@dwimm/plugin-bunq
Version:
DWIMM Plugin for bunq, a clean alternative to traditional banking
195 lines (162 loc) • 5.72 kB
JavaScript
;
const PluginTools = module.parent.exports;
const BunqClient = require('@bunq-community/bunq-js-client').default;
const PluginStorage = require('./storage');
const myStorage = new PluginStorage(PluginTools);
const client = new BunqClient(myStorage);
const ENCRYPTION_KEY = '455862556d715638324377507437336a';
new PluginTools.Config({
id: 'apiKey',
type: 'password',
label: 'plugins.label.apiKey'
});
new PluginTools.Config({
id: 'accounts',
type: 'text',
label: 'plugins.label.accounts',
placeholder: 'IBAN 1, IBAN 2'
});
module.exports = class {
/**
* @throws {PluginTools.ConfigurationError|PluginTools.ConfigurationErrors}
* @returns {Promise.<void>}
*/
static async validateConfig () {
if (!PluginTools.config('apiKey')) {
throw new PluginTools.ConfigurationError({
field: 'apiKey',
code: 'empty'
});
}
try {
await this.setup();
}
catch (err) {
console.log('validateConfig: setup() got error: ', err.response.data);
throw new PluginTools.ConfigurationErrors([
{
field: 'apiKey',
code: 'invalid'
}
]);
}
}
/**
* @returns {Promise.<PluginTools.Account[]>}
*/
static async getAccounts () {
await this.setup();
await this.sleep();
let accounts;
try {
accounts = await client.api.monetaryAccount.list(this.userId);
}
catch (err) {
console.log('getAccounts: got error: ', err.response.data);
throw err;
}
const whitelist = (PluginTools.config('accounts') || '')
.split(',')
.map(s => s.trim())
.filter(Boolean);
return accounts
.map(account => {
const accountType = account[Object.keys(account)[0]];
const accountIBAN = accountType.alias.find(a => a.type === 'IBAN');
if (!accountIBAN) {
console.log('getAccounts: account %s without IBAN, ignore it for now:', accountType.description);
return;
}
if (whitelist.length && whitelist.indexOf(accountIBAN.value) === -1) {
console.log('getAccounts: ignore %s with IBAN %s', accountType.description, accountIBAN.value);
return;
}
return new PluginTools.Account({
id: accountType.id.toString(),
name: accountType.description,
type: 'checking',
balance: Math.round(accountType.balance.value * 100)
});
})
.filter(account => account);
}
/**
* @param {string} accountId Account id submitted via getAccounts()
* @param {moment} since Moment of the timestamp
* @returns {Promise.<PluginTools.Transaction[]>}
*/
static async getTransactions (accountId, since) {
await this.setup();
await this.sleep();
const transactions = [];
let done = false;
let rawTransactions;
let oldestId;
do {
try {
rawTransactions = await client.api.payment.list(this.userId, accountId, {older_id: oldestId});
}
catch (err) {
console.log('getTransactions: got error: ', err.response.data);
throw err;
}
if (!rawTransactions) {
break;
}
rawTransactions
.map(payment => payment.Payment)
.forEach(payment => {
if (since.isAfter(payment.updated)) {
done = true;
}
transactions.push(
new PluginTools.Transaction({
id: payment.id.toString(),
time: new Date(payment.created),
payeeId: payment.counterparty_alias.display_name || payment.counterparty_alias.iban,
memo: payment.description,
amount: Math.round(payment.amount.value * 100),
status: 'cleared'
})
);
oldestId = payment.id;
});
} while (!done);
return transactions;
}
/**
* Do all the bunq setup stuff…
*
* @returns {Promise<void>}
*/
static async setup () {
// run the bunq application with our API key
await client.run(PluginTools.config('apiKey'), [], 'PRODUCTION', ENCRYPTION_KEY);
await this.sleep();
// install a new keypair
await client.install();
await this.sleep();
// register this device
await client.registerDevice('DWIMM Plugin');
await this.sleep();
// register a new session
await client.registerSession();
// get user id
let myUserId = await PluginTools.getStore('userId');
if (!myUserId) {
await this.sleep();
const users = await client.getUsers();
myUserId = users.UserPerson.id;
await PluginTools.setStore('userId', myUserId);
console.log('My User ID:', myUserId);
}
this.userId = myUserId;
}
static async sleep () {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 1000);
});
}
};