24 Commits

Author SHA1 Message Date
9fbaac20d3 1.0.15 2019-12-15 23:07:47 +00:00
270d1406c5 fix(transactions): enter a starting transaction 2019-12-15 23:07:46 +00:00
3cec57e3e7 1.0.14 2019-12-15 17:21:55 +00:00
cebb8a5555 fix(core): update 2019-12-15 17:21:54 +00:00
c3f60959c4 1.0.13 2019-12-15 17:21:24 +00:00
dc97525de6 fix(core): update 2019-12-15 17:21:23 +00:00
eeb93ef969 1.0.12 2019-10-03 14:44:38 +02:00
9cf02e32ef fix(core): update 2019-10-03 14:44:38 +02:00
d41019d341 1.0.11 2019-10-03 14:04:15 +02:00
27f120b608 fix(core): update 2019-10-03 14:04:15 +02:00
4978a2c272 1.0.10 2019-10-03 00:16:05 +02:00
a36f9634ce fix(core): update 2019-10-03 00:16:05 +02:00
f241956743 1.0.9 2019-10-03 00:04:41 +02:00
c40526c16c fix(core): update 2019-10-03 00:04:40 +02:00
945b69a659 1.0.8 2019-10-02 23:50:45 +02:00
0438e5d792 1.0.7 2019-10-02 23:38:54 +02:00
7e85acd404 1.0.6 2019-10-02 23:38:08 +02:00
ecdf7e46cc fix(core): update 2019-10-02 23:38:07 +02:00
7bd4cb67ae 1.0.5 2019-10-02 23:34:05 +02:00
cf5a462bd0 fix(core): update 2019-10-02 23:34:05 +02:00
328007fd97 1.0.4 2019-09-26 13:59:33 +02:00
def87cc216 fix(core): update 2019-09-26 13:59:33 +02:00
640ad81b70 1.0.3 2019-09-26 12:09:39 +02:00
49c18e2623 fix(core): update 2019-09-26 12:09:39 +02:00
10 changed files with 682 additions and 294 deletions

616
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@mojoio/bunq", "name": "@mojoio/bunq",
"version": "1.0.2", "version": "1.0.15",
"private": false, "private": false,
"description": "a bunq api abstraction package", "description": "a bunq api abstraction package",
"main": "dist/index.js", "main": "dist/index.js",
@ -9,16 +9,23 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "(tstest test/)", "test": "(tstest test/)",
"build": "(tsbuild)", "build": "(tsbuild --web)",
"format": "(gitzone format)" "format": "(gitzone format)"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.0.22", "@gitzone/tsbuild": "^2.0.22",
"@gitzone/tstest": "^1.0.15", "@gitzone/tstest": "^1.0.28",
"@pushrocks/tapbundle": "^3.0.7", "@pushrocks/qenv": "^4.0.6",
"@types/node": "^10.11.7", "@pushrocks/tapbundle": "^3.2.0",
"tslint": "^5.11.0", "@types/node": "^12.12.17",
"tslint": "^5.20.1",
"tslint-config-prettier": "^1.15.0" "tslint-config-prettier": "^1.15.0"
}, },
"dependencies": {} "dependencies": {
"@bunq-community/bunq-js-client": "^0.42.1",
"@pushrocks/smartcrypto": "^1.0.9",
"@pushrocks/smartfile": "^7.0.6",
"@pushrocks/smartpromise": "^3.0.6",
"json-store": "^1.0.0"
}
} }

2
qenv.yml Normal file
View File

@ -0,0 +1,2 @@
required:
- BUNQ_APIKEY

View File

@ -1,8 +1,41 @@
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as bunq from '../ts/index' import { Qenv } from '@pushrocks/qenv';
tap.test('first test', async () => { const testQenv = new Qenv('./', './.nogit/');
console.log(bunq.standardExport)
import * as bunq from '../ts';
let testBunqAccount: bunq.BunqAccount;
const testBunqOptions: bunq.IBunqConstructorOptions = {
apiKey: testQenv.getEnvVarOnDemand('BUNQ_APIKEY'),
deviceName: 'mojoiobunqpackage',
environment: 'SANDBOX'
};
tap.test('should create a valid bunq account', async () => {
testBunqAccount = new bunq.BunqAccount(testBunqOptions);
expect(testBunqAccount).to.be.instanceOf(bunq.BunqAccount);
});
tap.test('should init the client', async () => {
await testBunqAccount.init();
});
tap.test('should get accounts', async () => {
const accounts = await testBunqAccount.getAccounts();
console.log(accounts);
});
tap.test('should get transactions', async () => {
const accounts = await testBunqAccount.getAccounts();
for (const account of accounts) {
const transactions = await account.getTransactions();
console.log(transactions);
}
});
tap.test('should stop the instance', async () => {
await testBunqAccount.stop();
}) })
tap.start() tap.start();

102
ts/bunq.classes.account.ts Normal file
View File

@ -0,0 +1,102 @@
import * as plugins from './bunq.plugins';
import * as paths from './bunq.paths';
import { MonetaryAccount } from './bunq.classes.monetaryaccount';
export interface IBunqConstructorOptions {
deviceName: string;
apiKey: string;
environment: 'SANDBOX' | 'PRODUCTION';
}
/**
* the main bunq account
*/
export class BunqAccount {
public options: IBunqConstructorOptions;
public bunqJSClient: plugins.bunqCommunityClient.default;
public encryptionKey: string;
public permittedIps = []; // bunq will use the current ip if omitted
/**
* user id is needed for doing stuff like listing accounts;
*/
public userId: number;
constructor(optionsArg: IBunqConstructorOptions) {
this.options = optionsArg;
}
public async init() {
this.encryptionKey = plugins.smartcrypto.nodeForge.util.bytesToHex(
plugins.smartcrypto.nodeForge.random.getBytesSync(16)
);
// lets setup bunq client
await plugins.smartfile.fs.ensureDir(paths.nogitDir);
await plugins.smartfile.fs.ensureFile(paths.bunqJsonProductionFile, '{}');
await plugins.smartfile.fs.ensureFile(paths.bunqJsonSandboxFile, '{}');
let apiKey: string;
if (this.options.environment === 'SANDBOX') {
this.bunqJSClient = new plugins.bunqCommunityClient.default(plugins.JSONFileStore(paths.bunqJsonSandboxFile));
apiKey = await this.bunqJSClient.api.sandboxUser.post();
console.log(apiKey);
} else {
this.bunqJSClient = new plugins.bunqCommunityClient.default(plugins.JSONFileStore(paths.bunqJsonProductionFile));
apiKey = this.options.apiKey;
}
// run the bunq application with our API key
await this.bunqJSClient.run(
apiKey,
this.permittedIps,
this.options.environment,
this.encryptionKey
);
// install a new keypair
await this.bunqJSClient.install();
// register this device
await this.bunqJSClient.registerDevice(this.options.deviceName);
// register a new session
await this.bunqJSClient.registerSession();
await this.getUserId();
}
/**
* lists all users
*/
private async getUserId() {
const users = await this.bunqJSClient.api.user.list();
if (users.UserPerson) {
this.userId = users.UserPerson.id;
} else if (users.UserCompany) {
this.userId = users.UserCompany.id;
} else {
console.log('could not determine user id');
}
}
public async getAccounts() {
const apiMonetaryAccounts = await this.bunqJSClient.api.monetaryAccount.list(this.userId);
const accountsArray: MonetaryAccount[] = [];
for (const apiAccount of apiMonetaryAccounts) {
accountsArray.push(MonetaryAccount.fromAPIObject(this, apiAccount));
}
return accountsArray;
}
/**
* stops the instance
*/
public async stop() {
if (this.bunqJSClient) {
this.bunqJSClient.setKeepAlive(false);
await this.bunqJSClient.destroyApiSession();
this.bunqJSClient = null;
}
}
}

View File

@ -0,0 +1,113 @@
import * as plugins from './bunq.plugins';
import { BunqAccount } from './bunq.classes.account';
import { Transaction } from './bunq.classes.transaction';
export type TAccountType = 'joint' | 'savings' | 'bank';
/**
* a monetary account
*/
export class MonetaryAccount {
public static fromAPIObject(bunqAccountRef: BunqAccount, apiObject: any) {
const newMonetaryAccount = new this(bunqAccountRef);
let type: TAccountType;
let accessor: 'MonetaryAccountBank' | 'MonetaryAccountJoint' | 'MonetaryAccountSavings';
switch (true) {
case !!apiObject.MonetaryAccountBank:
type = 'bank';
accessor = 'MonetaryAccountBank';
break;
case !!apiObject.MonetaryAccountJoint:
type = 'joint';
accessor = 'MonetaryAccountJoint';
break;
case !!apiObject.MonetaryAccountSavings:
type = 'savings';
accessor = 'MonetaryAccountSavings';
break;
case !!apiObject.default:
console.log(apiObject);
throw new Error('unknown accoun type');
}
Object.assign(newMonetaryAccount, apiObject[accessor], {type});
return newMonetaryAccount;
}
// computed
public type: TAccountType;
// from API
public id: number;
public created: string;
public updated: string;
public alias: any[];
public avatar: {
uuid: string;
image: any[];
anchor_uuid: string;
};
public balance: {
currency: string;
value: string;
};
public country: string;
public currency: string;
public daily_limit: {
currency: string;
value: string;
};
public daily_spent: {
currency: string;
value: string;
};
public description: string;
public public_uuid: string;
public status: string;
public sub_status: string;
public timezone: string;
public user_id: number;
public monetary_account_profile: null;
public notification_filters: any[];
public setting: any[];
public connected_cards: any[];
public overdraft_limit: {
currency: string;
value: string;
};
public reason: string;
public reason_description: string;
public auto_save_id: null;
public all_auto_save_id: any[];
public bunqAccountRef: BunqAccount;
constructor(bunqAccountRefArg: BunqAccount) {
this.bunqAccountRef = bunqAccountRefArg;
}
/**
* gets all transactions no this account
*/
public async getTransactions(startingIdArg: number | false = false) {
const paginationOptions: {
count?: number;
newer_id?: number | false;
older_id?: number | false;
} = {
count: 200,
newer_id: startingIdArg
};
const apiTransactions = await this.bunqAccountRef.bunqJSClient.api.payment.list(this.bunqAccountRef.userId, this.id, paginationOptions);
const transactionsArray: Transaction[] = [];
for (const apiTransaction of apiTransactions) {
transactionsArray.push(Transaction.fromApiObject(this, apiTransaction));
}
return transactionsArray;
}
}

View File

@ -0,0 +1,45 @@
import * as plugins from './bunq.plugins';
import { MonetaryAccount } from './bunq.classes.monetaryaccount';
export class Transaction {
public static fromApiObject(monetaryAccountRefArg: MonetaryAccount, apiObjectArg: any) {
const newTransaction = new this(monetaryAccountRefArg);
Object.assign(newTransaction, apiObjectArg.Payment);
return newTransaction;
}
public id: number;
public created: string;
public updated: string;
public monetary_account_id: number;
public amount: {
currency: string;
value: string;
};
public description: string;
public type: 'MASTERCARD' | 'BUNQ';
public merchant_reference: null;
public alias: [Object];
public counterparty_alias: [Object];
public attachment: [];
public geolocation: null;
public batch_id: null;
public allow_chat: boolean;
public scheduled_id: null;
public address_billing: null;
public address_shipping: null;
public sub_type: 'PAYMENT';
public request_reference_split_the_bill: [];
public balance_after_mutation: {
currency: string;
value: string;
};
public monetaryAccountRef: MonetaryAccount;
constructor(monetaryAccountRefArg: MonetaryAccount) {
this.monetaryAccountRef = monetaryAccountRefArg;
}
}

7
ts/bunq.paths.ts Normal file
View File

@ -0,0 +1,7 @@
import * as plugins from './bunq.plugins';
export const packageDir = plugins.path.join(__dirname, '../');
export const nogitDir = plugins.path.join(packageDir, './.nogit/');
export const bunqJsonProductionFile = plugins.path.join(nogitDir, 'bunqproduction.json');
export const bunqJsonSandboxFile = plugins.path.join(nogitDir, 'bunqsandbox.json');

View File

@ -1,4 +1,23 @@
const removeme = {}; // node natice
import * as path from 'path';
export { export {
removeme path
} };
// @pushrocks scope
import * as smartcrypto from '@pushrocks/smartcrypto';
import * as smartfile from '@pushrocks/smartfile';
import * as smartpromise from '@pushrocks/smartpromise';
export {
smartcrypto,
smartfile,
smartpromise,
};
// third party
import JSONFileStore from "@bunq-community/bunq-js-client/dist/Stores/JSONFileStore";
import * as bunqCommunityClient from '@bunq-community/bunq-js-client';
export { JSONFileStore, bunqCommunityClient };

View File

@ -1,3 +1 @@
import * as plugins from './bunq.plugins'; export * from './bunq.classes.account';
export let standardExport = 'Hi there! :) This is an exported string';