add wallet auth support

This commit is contained in:
jejolare 2024-12-28 23:44:03 +07:00
parent f59a4eff6e
commit a7349d7600
3 changed files with 107 additions and 4 deletions

35
package-lock.json generated
View file

@ -17,9 +17,13 @@
"axios": "^1.7.2",
"big.js": "^6.2.1",
"decimal.js": "^10.4.3",
"node-forge": "^1.3.1",
"react": "^18.3.1",
"typescript": "^5.5.4",
"uuid": "^10.0.0"
},
"devDependencies": {
"@types/node-forge": "^1.3.11"
}
},
"node_modules/@types/big.js": {
@ -35,6 +39,15 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/node-forge": {
"version": "1.3.11",
"resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
"integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
@ -180,6 +193,14 @@
"node": ">= 0.6"
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"engines": {
"node": ">= 6.13.0"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@ -241,6 +262,15 @@
"undici-types": "~5.26.4"
}
},
"@types/node-forge": {
"version": "1.3.11",
"resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
"integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
@ -344,6 +374,11 @@
"mime-db": "1.52.0"
}
},
"node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",

View file

@ -31,6 +31,7 @@
"axios": "^1.7.2",
"big.js": "^6.2.1",
"decimal.js": "^10.4.3",
"node-forge": "^1.3.1",
"react": "^18.3.1",
"typescript": "^5.5.4",
"uuid": "^10.0.0"
@ -55,5 +56,8 @@
"types": "./shared/dist/index.d.ts"
}
},
"homepage": "https://github.com/hyle-team/zano_web3#readme"
"homepage": "https://github.com/hyle-team/zano_web3#readme",
"devDependencies": {
"@types/node-forge": "^1.3.11"
}
}

View file

@ -12,10 +12,12 @@ import {
import { ZANO_ASSET_ID, ZanoError } from "./utils";
import { APIAsset, APIBalance } from "./types";
import forge from "node-forge";
interface ConstructorParams {
walletUrl: string;
daemonUrl: string;
walletAuthToken?: string;
}
interface GetTxsParams {
@ -27,18 +29,71 @@ interface GetTxsParams {
update_provision_info?: boolean;
}
interface JWTPayload {
body_hash: string,
user: string,
salt: string,
exp: number
}
class ServerWallet {
private walletUrl: string;
private daemonUrl: string;
private walletAuthToken: string;
constructor(params: ConstructorParams) {
this.walletUrl = params.walletUrl;
this.daemonUrl = params.daemonUrl;
this.walletAuthToken = params.walletAuthToken || "";
}
private async fetchDaemon(method: string, params: any) {
const headers = { "Content-Type": "application/json" };
private generateRandomString(length: number) {
const bytes = forge.random.getBytesSync(Math.ceil(length / 2));
const hexString = forge.util.bytesToHex(bytes);
return hexString.substring(0, length);
}
private createJWSToken(payload: JWTPayload, secretStr: string): string {
const header = { alg: "HS256", typ: "JWT" };
const encodedHeader = Buffer.from(JSON.stringify(header))
.toString("base64")
.replace(/=/g, "");
const encodedPayload = Buffer.from(JSON.stringify(payload))
.toString("base64")
.replace(/=/g, "");
const signature = forge.hmac.create();
signature.start("sha256", secretStr);
signature.update(`${encodedHeader}.${encodedPayload}`);
const encodedSignature = forge.util
.encode64(signature.digest().getBytes())
.replace(/=/g, "");
return `${encodedHeader}.${encodedPayload}.${encodedSignature}`;
}
private generateAccessToken(httpBody: string) {
// Calculate the SHA-256 hash of the HTTP body
const md = forge.md.sha256.create();
md.update(httpBody);
const bodyHash = md.digest().toHex();
// Example payload
const payload = {
body_hash: bodyHash,
user: "zano_extension",
salt: this.generateRandomString(64),
exp: Math.floor(Date.now() / 1000) + 60, // Expires in 1 minute
};
return this.createJWSToken(payload, this.walletAuthToken);
}
private async fetchDaemon(method: string, params: any) {
const data = {
jsonrpc: "2.0",
id: 0,
@ -46,11 +101,15 @@ class ServerWallet {
params: params,
};
const headers = {
"Content-Type": "application/json",
"Zano-Access-Token": this.generateAccessToken(JSON.stringify(data)),
};
return axios.post(this.daemonUrl, data, { headers });
}
private async fetchWallet(method: string, params: any) {
const headers = { "Content-Type": "application/json" };
const data = {
jsonrpc: "2.0",
@ -59,6 +118,11 @@ class ServerWallet {
params: params,
};
const headers = {
"Content-Type": "application/json",
"Zano-Access-Token": this.generateAccessToken(JSON.stringify(data)),
};
return axios.post(this.walletUrl, data, { headers });
}