Skip to content

Commit

Permalink
feat: add meerkat.js and rollup build pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianbormann committed Dec 4, 2022
1 parent 40dbeae commit badce6b
Show file tree
Hide file tree
Showing 13 changed files with 12,929 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": [["@babel/env", { "modules": false }]]
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
dist/
.DS_Store

# Logs
logs
*.log
Expand Down
4 changes: 4 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"tabWidth": 2,
"singleQuote": true
}
54 changes: 54 additions & 0 deletions demo/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../dist/meerkat.min.js"></script>
<script>
var meerkat = new Meerkat({
seed: localStorage["bugout-demo-server-seed"],
announce: [
'udp://tracker.opentrackr.org:1337/announce',
'udp://open.tracker.cl:1337/announce',
'udp://opentracker.i2p.rocks:6969/announce',
'https://opentracker.i2p.rocks:443/announce',
'wss://tracker.files.fm:7073/announce',
'wss://spacetradersapi-chatbox.herokuapp.com:443/announce',
'ws://tracker.files.fm:7072/announce'
]
});
localStorage["bugout-demo-server-seed"] = meerkat.seed;

var connected = false;
meerkat.on("connections", function (clients) {
if (clients == 0 && connected == false) {
connected = true;
console.log("[info]: server ready");
}
console.log(`[info]: ${clients} clients connected`);
});

/*meerkat.register("api", function (address, args, callback) {
const api = { version: args.api.version, address: address }
for (method of args.api.methods) {
api[method] = () => new Promise((resolve, reject) => {
bugout.rpc(address, method, {}, (result) => resolve(result));
});
}
window.cardano = window.cardano || {};
window.cardano[args.api.name] = api;
console.log(`[info]: injected api of ${args.api.name} into window.cardano`);
});*/
</script>
<title>DApp</title>
</head>

<body>
<h1>Simple Example Dapp</h1>
</body>

</html>
6 changes: 6 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
transform: { '^.+\\.ts?$': 'ts-jest' },
testEnvironment: 'node',
testRegex: './*\\.(test|spec)?\\.(ts|tsx)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
};
185 changes: 185 additions & 0 deletions lib/bencode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { Buffer } from 'buffer';
import { BufferData } from '../types';

/**
* source:
* https://github.com/webtorrent/node-bencode/tree/3b1e2afeadbe63ab8892be5baecc6616d1f2dc15 (MIT)
*
* Added typescript & browser support
*/

function digitCount(value: number) {
// Add a digit for negative numbers, as the sign will be prefixed
const sign = value < 0 ? 1 : 0;
// Guard against negative numbers & zero going into log10(),
// as that would return -Infinity
value = Math.abs(Number(value || 1));
return Math.floor(Math.log10(value)) + 1 + sign;
}

function getType(value: BufferData) {
if (Buffer.isBuffer(value)) return 'buffer';
if (ArrayBuffer.isView(value)) return 'arraybufferview';
if (Array.isArray(value)) return 'array';
if (value instanceof Number) return 'number';
if (value instanceof Boolean) return 'boolean';
if (value instanceof Set) return 'set';
if (value instanceof Map) return 'map';
if (value instanceof String) return 'string';
if (value instanceof ArrayBuffer) return 'arraybuffer';
return typeof value;
}

export function encode(
data: Buffer | Array<any> | String | Object | Number | Boolean,
buffer?: Buffer,
offset?: number
) {
const buffers: Array<Buffer> = [];
encode._encode(buffers, data);
const result = Buffer.concat(buffers);
encode.bytes = result.length;

if (Buffer.isBuffer(buffer)) {
result.copy(buffer, offset);
return buffer;
}

return result;
}

encode.bytes = -1;
encode._floatConversionDetected = false;

encode._encode = function (buffers: Array<Buffer>, data: any) {
if (data == null) {
return;
}

switch (getType(data)) {
case 'buffer':
encode.buffer(buffers, data);
break;
case 'object':
encode.dict(buffers, data);
break;
case 'map':
encode.dictMap(buffers, data);
break;
case 'array':
encode.list(buffers, data);
break;
case 'set':
encode.listSet(buffers, data);
break;
case 'string':
encode.string(buffers, data);
break;
case 'number':
encode.number(buffers, data);
break;
case 'boolean':
encode.number(buffers, data);
break;
case 'arraybufferview':
encode.buffer(
buffers,
Buffer.from(data.buffer, data.byteOffset, data.byteLength)
);
break;
case 'arraybuffer':
encode.buffer(buffers, Buffer.from(data));
break;
}
};

const buffE = Buffer.from('e');
const buffD = Buffer.from('d');
const buffL = Buffer.from('l');

encode.buffer = function (buffers: Buffer[], data: Buffer) {
buffers.push(Buffer.from(data.length + ':'), data);
};

encode.string = function (buffers: Buffer[], data: string) {
buffers.push(Buffer.from(Buffer.byteLength(data) + ':' + data));
};

encode.number = function (buffers: Buffer[], data: number) {
const maxLo = 0x80000000;
const hi = (data / maxLo) << 0;
const lo = data % maxLo << 0;
const val = hi * maxLo + lo;

buffers.push(Buffer.from('i' + val + 'e'));

if (val !== data && !encode._floatConversionDetected) {
encode._floatConversionDetected = true;
console.warn(
'WARNING: Possible data corruption detected with value "' + data + '":',
'Bencoding only defines support for integers, value was converted to "' +
val +
'"'
);
console.trace();
}
};

encode.dict = function (buffers: Buffer[], data: any) {
buffers.push(buffD);

let j = 0;
let k;
// fix for issue #13 - sorted dicts
const keys = Object.keys(data).sort();
const kl = keys.length;

for (; j < kl; j++) {
k = keys[j];
if (data[k] == null) continue;
encode.string(buffers, k);
encode._encode(buffers, data[k]);
}

buffers.push(buffE);
};

encode.dictMap = function (buffers: Buffer[], data: Map<any, any>) {
buffers.push(buffD);

const keys = Array.from(data.keys()).sort();

for (const key of keys) {
if (data.get(key) == null) continue;
Buffer.isBuffer(key)
? encode._encode(buffers, key)
: encode.string(buffers, String(key));
encode._encode(buffers, data.get(key));
}

buffers.push(buffE);
};

encode.list = function (buffers: Buffer[], data: Array<any>) {
let i = 0;
const c = data.length;
buffers.push(buffL);

for (; i < c; i++) {
if (data[i] == null) continue;
encode._encode(buffers, data[i]);
}

buffers.push(buffE);
};

encode.listSet = function (buffers: Buffer[], data: any) {
buffers.push(buffL);

for (const item of data) {
if (item == null) continue;
encode._encode(buffers, item);
}

buffers.push(buffE);
};
22 changes: 22 additions & 0 deletions meerkat.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Meerkat from './meerkat';

describe('testing meerkat', () => {
test('create a new meerkat instance a throwing any error', (done) => {
const meerkat = new Meerkat();

let connected = false;
meerkat.on('connections', (clients) => {
if (clients == 0 && connected == false) {
connected = true;
console.log('[info]: server ready');
console.log(
`[info]: The address of this meerkat is ${meerkat.address()}`
);
}
console.log(`[info]: ${clients} clients connected`);

expect(clients.toBe(0));
done();
});
}, 30000);
});
Loading

0 comments on commit badce6b

Please sign in to comment.