mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
save work
This commit is contained in:
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "attach",
|
||||||
|
"name": "Attach NestJS WS",
|
||||||
|
"port": 9229,
|
||||||
|
"restart": true,
|
||||||
|
"stopOnEntry": false,
|
||||||
|
"protocol": "inspector"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+6
-1
@@ -1,5 +1,10 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Fastify"
|
"coinb",
|
||||||
|
"Fastify",
|
||||||
|
"merkle",
|
||||||
|
"nbits",
|
||||||
|
"ntime",
|
||||||
|
"prevhash"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Generated
+6847
-1255
File diff suppressed because it is too large
Load Diff
+5
-1
@@ -4,8 +4,12 @@ import { AppController } from './app.controller';
|
|||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { BitcoinStratumProvider } from './bitcoin-stratum.provider';
|
import { BitcoinStratumProvider } from './bitcoin-stratum.provider';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [
|
||||||
|
|
||||||
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, BitcoinStratumProvider],
|
providers: [AppService, BitcoinStratumProvider],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,84 +1,31 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { plainToInstance } from 'class-transformer';
|
|
||||||
import { validate, ValidatorOptions } from 'class-validator';
|
|
||||||
import { Server, Socket } from 'net';
|
import { Server, Socket } from 'net';
|
||||||
|
|
||||||
import { eMethod } from './models/enums/eMethod';
|
import { StratumV1Client } from './models/StratumV1Client';
|
||||||
import { SubscriptionMessage } from './models/SubscriptionMessage';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BitcoinStratumProvider {
|
export class BitcoinStratumProvider {
|
||||||
|
|
||||||
|
public clients: StratumV1Client[] = [];
|
||||||
|
|
||||||
private server: Server;
|
private server: Server;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.server = new Server((socket: Socket) => {
|
this.server = new Server((socket: Socket) => {
|
||||||
console.log('New client connected:', socket.remoteAddress);
|
console.log('New client connected:', socket.remoteAddress);
|
||||||
|
|
||||||
socket.on('data', this.handleData.bind(this, socket));
|
const client = new StratumV1Client(socket);
|
||||||
|
this.clients.push(client);
|
||||||
|
|
||||||
|
console.log('Number of Clients:', this.clients.length);
|
||||||
|
|
||||||
socket.on('end', () => {
|
|
||||||
// Handle socket disconnection
|
|
||||||
console.log('Client disconnected:', socket.remoteAddress);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('error', (error: Error) => {
|
|
||||||
// Handle socket error
|
|
||||||
console.error('Socket error:', error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private async handleData(socket: Socket, data: Buffer) {
|
|
||||||
const message = data.toString();
|
|
||||||
console.log('Received:', message);
|
|
||||||
|
|
||||||
// Parse the message and check if it's the initial subscription message
|
|
||||||
const parsedMessage = JSON.parse(message);
|
|
||||||
|
|
||||||
if (parsedMessage.method === eMethod.SUBSCRIBE) {
|
|
||||||
const subscriptionMessage = plainToInstance(
|
|
||||||
SubscriptionMessage,
|
|
||||||
parsedMessage,
|
|
||||||
);
|
|
||||||
|
|
||||||
const validatorOptions: ValidatorOptions = {
|
|
||||||
whitelist: true,
|
|
||||||
forbidNonWhitelisted: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const errors = await validate(subscriptionMessage, validatorOptions);
|
|
||||||
|
|
||||||
if (errors.length === 0) {
|
|
||||||
const response = this.buildSubscriptionResponse(subscriptionMessage.id);
|
|
||||||
socket.write(JSON.stringify(response) + '\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildSubscriptionResponse(requestId: number): any {
|
|
||||||
const subscriptionResponse = {
|
|
||||||
id: requestId,
|
|
||||||
result: [
|
|
||||||
[
|
|
||||||
[
|
|
||||||
'mining.set_difficulty',
|
|
||||||
'0000000c9c7a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'mining.notify',
|
|
||||||
'0000000c9c7a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'a843cfc2',
|
|
||||||
4,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return subscriptionResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import * as crypto from 'crypto';
|
||||||
|
|
||||||
|
import { eResponseMethod } from './enums/eResponseMethod';
|
||||||
|
|
||||||
|
export class MiningJob {
|
||||||
|
public id: number;
|
||||||
|
public method: eResponseMethod.MINING_NOTIFY;
|
||||||
|
public params: string[];
|
||||||
|
|
||||||
|
|
||||||
|
public job_id: string; // ID of the job. Use this ID while submitting share generated from this job.
|
||||||
|
public prevhash: string; // Hash of previous block.
|
||||||
|
public coinb1: string; // Initial part of coinbase transaction.
|
||||||
|
public coinb2: string; // Final part of coinbase transaction.
|
||||||
|
public merkle_branch: string[]; // List of hashes, will be used for calculation of merkle root. This is not a list of all transactions, it only contains prepared hashes of steps of merkle tree algorithm.
|
||||||
|
public version: string; // Bitcoin block version.
|
||||||
|
public nbits: string; // Encoded current network difficulty
|
||||||
|
public ntime: string; // Current ntime/
|
||||||
|
public clean_jobs: boolean; // When true, server indicates that submitting shares from previous jobs don't have a sense and such shares will be rejected. When this flag is set, miner should also drop all previous jobs too.
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
|
||||||
|
this.job_id = null;
|
||||||
|
this.prevhash = null;
|
||||||
|
this.coinb1 = null;
|
||||||
|
this.coinb2 = null;
|
||||||
|
this.merkle_branch = null;
|
||||||
|
this.version = null;
|
||||||
|
this.nbits = null;
|
||||||
|
this.ntime = Math.floor(new Date().getTime() / 1000).toString();
|
||||||
|
this.clean_jobs = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
method: this.method,
|
||||||
|
params: [
|
||||||
|
this.job_id,
|
||||||
|
this.prevhash,
|
||||||
|
this.coinb1,
|
||||||
|
this.coinb2,
|
||||||
|
this.merkle_branch,
|
||||||
|
this.version,
|
||||||
|
this.nbits,
|
||||||
|
this.ntime,
|
||||||
|
this.clean_jobs
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public buildCoinbaseHashBin(coinbase: string): Buffer {
|
||||||
|
const sha256 = crypto.createHash('sha256');
|
||||||
|
const sha256Digest = sha256.update(Buffer.from(coinbase, 'hex')).digest();
|
||||||
|
|
||||||
|
const coinbaseHashSha256 = crypto.createHash('sha256');
|
||||||
|
const coinbaseHash = coinbaseHashSha256.update(sha256Digest).digest();
|
||||||
|
|
||||||
|
return coinbaseHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildMerkleRoot(merkleBranch: string[], coinbaseHashBin: Buffer): string {
|
||||||
|
let merkleRoot = coinbaseHashBin;
|
||||||
|
for (const h of merkleBranch) {
|
||||||
|
const concatenatedBuffer = Buffer.concat([merkleRoot, Buffer.from(h, 'hex')]);
|
||||||
|
merkleRoot = this.doubleSHA(concatenatedBuffer);
|
||||||
|
}
|
||||||
|
return merkleRoot.toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
private doubleSHA(data: Buffer): Buffer {
|
||||||
|
const sha256 = crypto.createHash('sha256');
|
||||||
|
const sha256Digest = sha256.update(data).digest();
|
||||||
|
|
||||||
|
const doubleSha256 = crypto.createHash('sha256');
|
||||||
|
const doubleSha256Digest = doubleSha256.update(sha256Digest).digest();
|
||||||
|
|
||||||
|
return doubleSha256Digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
import { plainToInstance } from 'class-transformer';
|
||||||
|
import { validate, ValidatorOptions } from 'class-validator';
|
||||||
|
import { Socket } from 'net';
|
||||||
|
import { interval } from 'rxjs';
|
||||||
|
|
||||||
|
import { eRequestMethod } from './enums/eRequestMethod';
|
||||||
|
import { eResponseMethod } from './enums/eResponseMethod';
|
||||||
|
import { AuthorizationMessage } from './stratum-messages/AuthorizationMessage';
|
||||||
|
import { ConfigurationMessage } from './stratum-messages/ConfigurationMessage';
|
||||||
|
import { MiningSubmitMessage } from './stratum-messages/MiningSubmitMessage';
|
||||||
|
import { SubscriptionMessage } from './stratum-messages/SubscriptionMessage';
|
||||||
|
import { SuggestDifficulty } from './stratum-messages/SuggestDifficultyMessage';
|
||||||
|
|
||||||
|
export class StratumV1Client {
|
||||||
|
|
||||||
|
private clientSubscription: SubscriptionMessage;
|
||||||
|
private clientConfiguration: ConfigurationMessage;
|
||||||
|
private clientAuthorization: AuthorizationMessage;
|
||||||
|
private clientSuggestedDifficulty: SuggestDifficulty;
|
||||||
|
|
||||||
|
public initialized = false;
|
||||||
|
|
||||||
|
private interval: NodeJS.Timer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private readonly socket: Socket) {
|
||||||
|
|
||||||
|
this.socket.on('data', this.handleData.bind(this, this.socket));
|
||||||
|
|
||||||
|
this.socket.on('end', () => {
|
||||||
|
// Handle socket disconnection
|
||||||
|
console.log('Client disconnected:', socket.remoteAddress);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on('error', (error: Error) => {
|
||||||
|
// Handle socket error
|
||||||
|
console.error('Socket error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async handleData(socket: Socket, data: Buffer) {
|
||||||
|
const message = data.toString();
|
||||||
|
|
||||||
|
message.split('\n')
|
||||||
|
.filter(m => m.length > 0)
|
||||||
|
.forEach(this.handleMessage.bind(this, socket));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async handleMessage(socket: Socket, message: string) {
|
||||||
|
console.log('Received:', message);
|
||||||
|
|
||||||
|
// Parse the message and check if it's the initial subscription message
|
||||||
|
let parsedMessage = null;
|
||||||
|
try {
|
||||||
|
parsedMessage = JSON.parse(message);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (parsedMessage.method) {
|
||||||
|
case eRequestMethod.SUBSCRIBE: {
|
||||||
|
const subscriptionMessage = plainToInstance(
|
||||||
|
SubscriptionMessage,
|
||||||
|
parsedMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatorOptions: ValidatorOptions = {
|
||||||
|
whitelist: true,
|
||||||
|
forbidNonWhitelisted: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const errors = await validate(subscriptionMessage, validatorOptions);
|
||||||
|
|
||||||
|
if (errors.length === 0) {
|
||||||
|
this.clientSubscription = subscriptionMessage;
|
||||||
|
|
||||||
|
socket.write(JSON.stringify(this.clientSubscription.response()) + '\n');
|
||||||
|
} else {
|
||||||
|
console.error(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eRequestMethod.CONFIGURE: {
|
||||||
|
|
||||||
|
const configurationMessage = plainToInstance(
|
||||||
|
ConfigurationMessage,
|
||||||
|
parsedMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatorOptions: ValidatorOptions = {
|
||||||
|
whitelist: true,
|
||||||
|
forbidNonWhitelisted: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const errors = await validate(configurationMessage, validatorOptions);
|
||||||
|
|
||||||
|
if (errors.length === 0) {
|
||||||
|
this.clientConfiguration = configurationMessage;
|
||||||
|
//const response = this.buildSubscriptionResponse(configurationMessage.id);
|
||||||
|
socket.write(JSON.stringify(this.clientConfiguration.response()) + '\n');
|
||||||
|
} else {
|
||||||
|
console.error(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eRequestMethod.AUTHORIZE: {
|
||||||
|
const authorizationMessage = plainToInstance(
|
||||||
|
AuthorizationMessage,
|
||||||
|
parsedMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatorOptions: ValidatorOptions = {
|
||||||
|
whitelist: true,
|
||||||
|
forbidNonWhitelisted: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const errors = await validate(authorizationMessage, validatorOptions);
|
||||||
|
|
||||||
|
if (errors.length === 0) {
|
||||||
|
this.clientAuthorization = authorizationMessage;
|
||||||
|
this.clientAuthorization.parse();
|
||||||
|
//const response = this.buildSubscriptionResponse(authorizationMessage.id);
|
||||||
|
socket.write(JSON.stringify(this.clientAuthorization.response()) + '\n');
|
||||||
|
} else {
|
||||||
|
console.error(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eRequestMethod.SUGGEST_DIFFICULTY: {
|
||||||
|
|
||||||
|
const suggestDifficultyMessage = plainToInstance(
|
||||||
|
SuggestDifficulty,
|
||||||
|
parsedMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatorOptions: ValidatorOptions = {
|
||||||
|
whitelist: true,
|
||||||
|
forbidNonWhitelisted: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const errors = await validate(suggestDifficultyMessage, validatorOptions);
|
||||||
|
|
||||||
|
if (errors.length === 0) {
|
||||||
|
this.clientSuggestedDifficulty = suggestDifficultyMessage;
|
||||||
|
socket.write(JSON.stringify(this.clientSuggestedDifficulty.response()) + '\n');
|
||||||
|
} else {
|
||||||
|
console.error(errors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eRequestMethod.SUBMIT: {
|
||||||
|
const miningSubmitMessage = plainToInstance(
|
||||||
|
MiningSubmitMessage,
|
||||||
|
parsedMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatorOptions: ValidatorOptions = {
|
||||||
|
whitelist: true,
|
||||||
|
forbidNonWhitelisted: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const errors = await validate(miningSubmitMessage, validatorOptions);
|
||||||
|
|
||||||
|
if (errors.length === 0) {
|
||||||
|
//this.clientSuggestedDifficulty = miningSubmitMessage;
|
||||||
|
socket.write(JSON.stringify(miningSubmitMessage.response()) + '\n');
|
||||||
|
} else {
|
||||||
|
console.error(errors);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.initialized) {
|
||||||
|
if (this.clientSubscription != null
|
||||||
|
&& this.clientConfiguration != null
|
||||||
|
&& this.clientAuthorization != null
|
||||||
|
&& this.clientSuggestedDifficulty != null) {
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
|
this.manualMiningNotify();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private manualMiningNotify() {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.miningNotify();
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
this.miningNotify();
|
||||||
|
}, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private miningNotify() {
|
||||||
|
const notification = {
|
||||||
|
id: null,
|
||||||
|
method: eResponseMethod.MINING_NOTIFY,
|
||||||
|
params: [
|
||||||
|
'64756fab0000442e',
|
||||||
|
'39dbb5b4e173e1f9ac6f6ad92e9dde300effce6b0003ea860000000000000000',
|
||||||
|
'01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff35033e1c0c00048fef83640447483e060c',
|
||||||
|
'0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff03e1c7872600000000160014876961d21eaba10f0701dcc78f6624a4c682270d384dc900000000001976a914f4cbe6c6bb3a8535c963169c22963d3a20e7686988ac0000000000000000266a24aa21a9ed751521cd94e7780a9a13ac8bb1da5410d30acdd2f6348876835623b04b2dc83b00000000',
|
||||||
|
[
|
||||||
|
'c0c9d351b9e094dd85bc64c8909dece6226269ebfe173bb74ba2f89c51df7066',
|
||||||
|
'6c56f47cbfaef5688bb338bc56c4189530f12cdb98f8cc46b6a12053f1e69fdd',
|
||||||
|
'697cdaa8d15691f7b30dfe7f6c33957f04cfc8126fed16d2fe38c96adaa59c41',
|
||||||
|
'cbe8aa6e0343884a40b850df8fd3c2ffcc026acec392ce93f9e28619eb0d3dac',
|
||||||
|
'e023091cf0fc02684c77730a34791181a44be92f966ba579aa4cf6e98d754548',
|
||||||
|
'6b8fea64efe363e02ff42a4257d76a77381006eade804c8a8c9b96c9c98b1d9e',
|
||||||
|
'1c936bc5320cdbbe7348cdd4bf272529822e9d34dfa8e0ee0041eae635891cc3',
|
||||||
|
'8fed2682a3c95863c6b9440b1a47abdd3d4230181f61edf0daa2e5f0befbcf65',
|
||||||
|
'0837c4d162e1086ec553ea90af4be4f9747958e556598cc38cb08149e58227b1',
|
||||||
|
'0b5287e647c7cb6f2fcdf13d5ef3bf091d1137773d7695405d0b2768f442ee78',
|
||||||
|
'71eaff9247b5556fa88bca6da2e055d5db8aef2969a2d5c68f8e7efd7d39a283'
|
||||||
|
],
|
||||||
|
'20000000',
|
||||||
|
'17057e69',
|
||||||
|
'6483ef8f',
|
||||||
|
true
|
||||||
|
],
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.socket.write(JSON.stringify(notification) + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { eMethod } from './enums/eMethod';
|
|
||||||
|
|
||||||
export class SubscriptionMessage {
|
|
||||||
id: number;
|
|
||||||
method: eMethod.SUBSCRIBE;
|
|
||||||
params: string[];
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export enum eMethod {
|
|
||||||
SUBSCRIBE = 'mining.subscribe'
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export enum eRequestMethod {
|
||||||
|
SUBSCRIBE = 'mining.subscribe',
|
||||||
|
CONFIGURE = 'mining.configure',
|
||||||
|
AUTHORIZE = 'mining.authorize',
|
||||||
|
SUGGEST_DIFFICULTY = 'mining.suggest_difficulty',
|
||||||
|
SUBMIT = 'mining.submit',
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export enum eResponseMethod {
|
||||||
|
SET_DIFFICULTY = 'mining.set_difficulty',
|
||||||
|
MINING_NOTIFY = 'mining.notify',
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { ArrayMaxSize, ArrayMinSize, IsArray } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
|
export class AuthorizationMessage extends StratumBaseMessage {
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@ArrayMinSize(2)
|
||||||
|
@ArrayMaxSize(2)
|
||||||
|
params: string[];
|
||||||
|
|
||||||
|
public username: string;
|
||||||
|
|
||||||
|
public password: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.method = eRequestMethod.AUTHORIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse() {
|
||||||
|
this.username = this.params[0];
|
||||||
|
this.password = this.params[1];
|
||||||
|
console.log(`Username ${this.username}, Password: ${this.password}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
error: null,
|
||||||
|
result: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { IsArray } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
|
export class ConfigurationMessage extends StratumBaseMessage {
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
params: string[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.method = eRequestMethod.CONFIGURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
error: null,
|
||||||
|
result: {
|
||||||
|
'version-rolling': true,
|
||||||
|
'version-rolling.mask': '1fffe000'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { ArrayMaxSize, ArrayMinSize, IsArray } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
|
export class MiningSubmitMessage extends StratumBaseMessage {
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@ArrayMinSize(5)
|
||||||
|
@ArrayMaxSize(5)
|
||||||
|
params: string[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.method = eRequestMethod.AUTHORIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
error: null,
|
||||||
|
result: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { IsEnum, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
|
||||||
|
export class StratumBaseMessage {
|
||||||
|
@IsNumber()
|
||||||
|
id: number;
|
||||||
|
@IsEnum(eRequestMethod)
|
||||||
|
method: eRequestMethod;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { IsArray } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
|
export class SubscriptionMessage extends StratumBaseMessage {
|
||||||
|
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
params: string[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.method = eRequestMethod.SUBSCRIBE;
|
||||||
|
|
||||||
|
console.log('constructor SubscriptionMessage');
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
error: null,
|
||||||
|
result: [
|
||||||
|
[
|
||||||
|
['mining.notify', '64d8c004']
|
||||||
|
], //subscription details
|
||||||
|
'ccc5d664', //Extranonce1 - Hex-encoded, per-connection unique string which will be used for coinbase serialization later. Keep it safe!
|
||||||
|
8 //Extranonce2_size - Represents expected length of extranonce2 which will be generated by the miner.
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { ArrayMaxSize, ArrayMinSize, IsArray, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { eResponseMethod } from '../enums/eResponseMethod';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
|
export class SuggestDifficulty extends StratumBaseMessage {
|
||||||
|
@IsArray()
|
||||||
|
@ArrayMinSize(1)
|
||||||
|
@ArrayMaxSize(1)
|
||||||
|
@IsNumber({}, { each: true })
|
||||||
|
params: string[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.method = eRequestMethod.SUGGEST_DIFFICULTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public response() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
method: eResponseMethod.SET_DIFFICULTY,
|
||||||
|
params: [1024]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user