Push wChain Project (web3)

This commit is contained in:
syn 2024-10-08 09:40:16 +07:00
commit 53cfffc40a
16 changed files with 4215 additions and 0 deletions

22
README.md Normal file
View File

@ -0,0 +1,22 @@
<h1>wChainGPRC</h1>
<img src="img/Screenshot.png">
<p>Intro:</p>
<p>wChainGPRC adalah implementasi sederhana dari sebuah server JSON-RPC yang berfungsi untuk melakukan berbagai operasi blockchain, termasuk mendapatkan informasi Chain ID, mengecek saldo, mengelola wallet, dan memantau transaksi. Proyek ini bertujuan untuk menyediakan antarmuka testing yang mudah digunakan untuk berbagai fungsi dasar blockchain.</p>
<p>Proyek ini didesain untuk penggunaan uji coba, terutama bagi pengembang yang ingin mempelajari interaksi dasar antara JSON-RPC dan blockchain. Dengan menggunakan curl, Anda dapat menguji berbagai metode dan memastikan alur kerja blockchain berjalan sesuai ekspektasi sebelum diterapkan ke lingkungan produksi yang lebih kompleks.</p>
### install
`$ npm insttall`
### Run Server
`$ node server.js`
### Run GPRC
`$ node grpc.js`
<h2>Dokumentasi & Pengujian</h2>
<a href="">Wiki Dokumentasi & Pengujian</a>

33
blockchain.proto Normal file
View File

@ -0,0 +1,33 @@
syntax = "proto3";
package blockchain;
service BlockchainService {
rpc GetBalance (BalanceRequest) returns (BalanceResponse);
rpc SendTransaction (TransactionRequest) returns (TransactionResponse);
rpc GetChainId (ChainIdRequest) returns (ChainIdResponse);
}
message BalanceRequest {
string address = 1;
}
message BalanceResponse {
string balance = 1;
}
message TransactionRequest {
string from = 1;
string to = 2;
string amount = 3;
}
message TransactionResponse {
string transactionHash = 1;
}
message ChainIdRequest {}
message ChainIdResponse {
string chainId = 1;
}

11
client.js Normal file
View File

@ -0,0 +1,11 @@
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('blockchain.proto', {});
const blockchainProto = grpc.loadPackageDefinition(packageDefinition).blockchain;
const client = new blockchainProto.BlockchainService(
'localhost:50051',
grpc.credentials.createInsecure()
);
module.exports = client;

25
grpc.js Normal file
View File

@ -0,0 +1,25 @@
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('blockchain.proto', {});
const blockchainProto = grpc.loadPackageDefinition(packageDefinition).blockchain;
const server = new grpc.Server();
server.addService(blockchainProto.BlockchainService.service, {
GetBalance: (call, callback) => {
const balance = "1000"; // Implementasi mendapatkan saldo (dalam bentuk desimal)
callback(null, { balance: balance });
},
SendTransaction: (call, callback) => {
const transactionHash = "0x1234567890abcdef"; // Implementasi mengirim transaksi (dalam bentuk hexadesimal)
callback(null, { transactionHash: transactionHash });
},
GetChainId: (call, callback) => {
const chainId = "14006"; // Ganti dengan 14006 tanpa nol di depan(dalam bentuk desimal), Gunakan ChainID yang belum pernah di pakai oleh Blockchain lain.
callback(null, { chainId: chainId });
},
});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
console.log('Server gRPC berjalan di port 50051');
});

BIN
img/Screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

2717
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "wchaingprc",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"services": "node server"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@ethereumjs/common": "^4.3.0",
"@ethereumjs/tx": "^5.3.0",
"@grpc/grpc-js": "^1.10.10",
"@grpc/proto-loader": "^0.7.13",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"ethereumjs-tx": "^2.1.2",
"ethereumjs-wallet": "^1.0.2",
"express": "^4.19.2",
"fs": "^0.0.1-security",
"http-proxy-middleware": "^3.0.0",
"path": "^0.12.7",
"web3": "^4.10.0"
}
}

View File

@ -0,0 +1,840 @@
{
"name": "scan-testblock",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "scan-testblock",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^1.7.2",
"express": "^4.19.2"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT"
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"statuses": "2.0.1",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
"license": "MIT"
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-inspect": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
"license": "MIT"
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/qs": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"license": "MIT",
"dependencies": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
}
}
}

View File

@ -0,0 +1,16 @@
{
"name": "scan-testblock",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"axios": "^1.7.2",
"express": "^4.19.2"
}
}

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Explorer</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Block Explorer</h1>
<div>
<input type="text" id="blockNumber" placeholder="Enter block number">
<button onclick="fetchBlock()">Fetch Block</button>
</div>
<div>
<input type="text" id="txHash" placeholder="Enter transaction hash">
<button onclick="fetchTransaction()">Fetch Transaction</button>
</div>
<div>
<input type="text" id="address" placeholder="Enter wallet address">
<button onclick="fetchAddress()">Fetch Address</button>
</div>
<div>
<input type="text" id="addressTx" placeholder="Enter wallet address for transactions">
<button onclick="fetchAddressTransactions()">Fetch Address Transactions</button>
</div>
<div>
<input type="text" id="contractFrom" placeholder="Enter from address">
<input type="text" id="contractData" placeholder="Enter contract data">
<input type="text" id="contractGas" placeholder="Enter gas limit">
<button onclick="deployContract()">Deploy Contract</button>
</div>
<div id="result"></div>
<script src="scripts.js"></script>
</body>
</html>

View File

@ -0,0 +1,44 @@
async function fetchBlock() {
const blockNumber = document.getElementById('blockNumber').value;
const response = await fetch(`/block/${blockNumber}`);
const data = await response.json();
document.getElementById('result').innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
async function fetchTransaction() {
const txHash = document.getElementById('txHash').value;
const response = await fetch(`/transaction/${txHash}`);
const data = await response.json();
document.getElementById('result').innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
async function fetchAddress() {
const address = document.getElementById('address').value;
const response = await fetch(`/address/${address}`);
const data = await response.json();
document.getElementById('result').innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
async function fetchAddressTransactions() {
const address = document.getElementById('addressTx').value;
const response = await fetch(`/address/${address}/transactions`);
const data = await response.json();
document.getElementById('result').innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
}
async function deployContract() {
const from = document.getElementById('contractFrom').value;
const data = document.getElementById('contractData').value;
const gas = document.getElementById('contractGas').value;
const response = await fetch('/deployContract', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ from, data, gas })
});
const result = await response.json();
document.getElementById('result').innerHTML = `<pre>${JSON.stringify(result, null, 2)}</pre>`;
}

View File

@ -0,0 +1,29 @@
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
text-align: center;
}
div {
margin-bottom: 20px;
}
input {
padding: 10px;
margin-right: 10px;
width: 300px;
}
button {
padding: 10px;
}
#result {
margin-top: 20px;
padding: 20px;
border: 1px solid #ccc;
background-color: #f9f9f9;
}

View File

@ -0,0 +1,127 @@
const express = require('express');
const axios = require('axios');
const path = require('path');
const fs = require('fs');
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.use(express.json());
const rpcUrl = 'http://localhost:8080/blockchain'; // Ganti dengan URL RPC node Anda
let contractsDb = {};
if (fs.existsSync('contracts.json')) {
contractsDb = JSON.parse(fs.readFileSync('contracts.json'));
}
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.get('/block/:number', async (req, res) => {
const blockNumber = req.params.number;
try {
const response = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_getBlockByNumber',
params: [blockNumber, true],
id: 1
});
res.json(response.data);
} catch (error) {
res.status(500).send('Error fetching block data');
}
});
app.get('/transaction/:hash', async (req, res) => {
const txHash = req.params.hash;
try {
const response = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_getTransactionByHash',
params: [txHash],
id: 1
});
res.json(response.data);
} catch (error) {
res.status(500).send('Error fetching transaction data');
}
});
app.get('/address/:address', async (req, res) => {
const address = req.params.address;
try {
const response = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_getBalance',
params: [address, 'latest'],
id: 1
});
res.json(response.data);
} catch (error) {
res.status(500).send('Error fetching address data');
}
});
app.get('/address/:address/transactions', async (req, res) => {
const address = req.params.address;
const transactions = [];
try {
// Assuming the blockchain has 100 blocks for simplicity.
for (let i = 0; i < 100; i++) {
const blockResponse = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_getBlockByNumber',
params: [i.toString(16), true],
id: 1
});
const block = blockResponse.data.result;
block.transactions.forEach(tx => {
if (tx.from.toLowerCase() === address.toLowerCase() || tx.to.toLowerCase() === address.toLowerCase()) {
transactions.push(tx);
}
});
}
res.json(transactions);
} catch (error) {
res.status(500).send('Error fetching transactions for address');
}
});
app.post('/deployContract', async (req, res) => {
const { from, data, gas } = req.body;
try {
const response = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_sendTransaction',
params: [{
from: from,
data: data,
gas: gas
}],
id: 1
});
const txHash = response.data.result;
const receiptResponse = await axios.post(rpcUrl, {
jsonrpc: '2.0',
method: 'eth_getTransactionReceipt',
params: [txHash],
id: 1
});
const contractAddress = receiptResponse.data.result.contractAddress;
contractsDb[contractAddress] = { txHash, from, data };
fs.writeFileSync('contracts.json', JSON.stringify(contractsDb, null, 2));
res.json({ contractAddress });
} catch (error) {
res.status(500).send('Error deploying contract');
}
});
app.listen(PORT, () => {
console.log(`Block explorer server running on port ${PORT}`);
});

259
server.js Normal file
View File

@ -0,0 +1,259 @@
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const fs = require('fs');
const path = require('path');
const Wallet = require('ethereumjs-wallet').default;
const client = require('./client');
const app = express();
app.use(cors());
app.use(bodyParser.json());
const CHAIN_ID = '14006'; // Definisikan Chain ID di sini
const WALLET_DB_PATH = path.join(__dirname, 'wallets.json');
// Fungsi untuk membaca database wallet dari file JSON
function readWalletsDB() {
return new Promise((resolve, reject) => {
fs.readFile(WALLET_DB_PATH, 'utf8', (err, data) => {
if (err) {
return reject(err);
}
resolve(JSON.parse(data));
});
});
}
// Fungsi untuk menulis database wallet ke file JSON
function writeWalletsDB(wallets) {
return new Promise((resolve, reject) => {
fs.writeFile(WALLET_DB_PATH, JSON.stringify(wallets, null, 2), 'utf8', (err) => {
if (err) {
return reject(err);
}
resolve();
});
});
}
// Fungsi untuk membuat wallet acak
function createRandomWallet() {
const wallet = Wallet.generate();
return {
address: wallet.getAddressString(),
privateKey: wallet.getPrivateKeyString(),
balance: '0x0'
};
}
app.post('/blockchain', async (req, res) => {
const { method, params, id } = req.body;
console.log('Received request:', req.body);
if (method === 'GetChainId') {
client.GetChainId({}, (error, response) => {
if (error) {
console.error('Error in GetChainId:', error);
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal JSON-RPC error',
data: error.message
},
id: id
});
} else {
console.log('GetChainId response:', response);
res.json({
jsonrpc: '2.0',
result: { chainId: response.chainId },
id: id
});
}
});
} else if (method === 'eth_chainId') {
console.log('Handling eth_chainId method');
res.json({
jsonrpc: '2.0',
result: `0x${parseInt(CHAIN_ID).toString(16)}`, // Kembalikan Chain ID dalam format heksadesimal
id: id
});
} else if (method === 'eth_blockNumber') {
console.log('Handling eth_blockNumber method');
// Kembalikan block number, sebagai contoh kita akan mengembalikan nilai statis
res.json({
jsonrpc: '2.0',
result: '0x1', // Kembalikan block number dalam format heksadesimal
id: id
});
} else if (method === 'net_version') {
console.log('Handling net_version method');
res.json({
jsonrpc: '2.0',
result: CHAIN_ID, // Kembalikan Chain ID
id: id
});
} else if (method === 'eth_getBalance') {
console.log('Handling eth_getBalance method');
const [address, block] = params;
try {
const walletsDB = await readWalletsDB();
const wallet = walletsDB.wallets.find(w => w.address.toLowerCase() === address.toLowerCase());
if (wallet) {
res.json({
jsonrpc: '2.0',
result: wallet.balance, // Kembalikan balance dalam format heksadesimal
id: id
});
} else {
res.status(404).json({
jsonrpc: '2.0',
error: {
code: -32602,
message: 'Address not found'
},
id: id
});
}
} catch (error) {
console.error('Error in eth_getBalance:', error);
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal JSON-RPC error',
data: error.message
},
id: id
});
}
} else if (method === 'eth_getBlockByNumber') {
console.log('Handling eth_getBlockByNumber method');
// Kembalikan block, sebagai contoh ini akan mengembalikan nilai statis
res.json({
jsonrpc: '2.0',
result: {
number: '0x1',
hash: '0x0',
parentHash: '0x0',
nonce: '0x0',
sha3Uncles: '0x0',
logsBloom: '0x0',
transactionsRoot: '0x0',
stateRoot: '0x0',
receiptsRoot: '0x0',
miner: '0x0',
difficulty: '0x0',
totalDifficulty: '0x0',
extraData: '0x0',
size: '0x0',
gasLimit: '0x0',
gasUsed: '0x0',
timestamp: '0x0',
transactions: [],
uncles: []
}, // Kembalikan block dalam format JSON
id: id
});
} else if (method === 'addWallets') {
console.log('Handling addWallets method');
const [numberOfWallets] = params;
try {
const walletsDB = await readWalletsDB();
for (let i = 0; i < numberOfWallets; i++) {
const newWallet = createRandomWallet();
walletsDB.wallets.push(newWallet);
}
await writeWalletsDB(walletsDB);
res.json({
jsonrpc: '2.0',
result: `${numberOfWallets} wallets added successfully`,
id: id
});
} catch (error) {
console.error('Error in addWallets:', error);
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal JSON-RPC error',
data: error.message
},
id: id
});
}
} else if (method === 'addBalance') {
console.log('Handling addBalance method');
const [address, amount] = params;
try {
const walletsDB = await readWalletsDB();
const wallet = walletsDB.wallets.find(w => w.address.toLowerCase() === address.toLowerCase());
if (wallet) {
// Konversi saldo dari desimal ke heksadesimal (sebaiknya jika di perlukan untuk pengembangan lebih lanjut gunkan hexadesimal untuk kedua nya)
const amountInHex = BigInt(amount).toString(16);
wallet.balance = (BigInt(wallet.balance) + BigInt('0x' + amountInHex)).toString(16);
await writeWalletsDB(walletsDB);
res.json({
jsonrpc: '2.0',
result: `Balance added successfully`,
id: id
});
} else {
res.status(404).json({
jsonrpc: '2.0',
error: {
code: -32602,
message: 'Address not found'
},
id: id
});
}
} catch (error) {
console.error('Error in addBalance:', error);
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal JSON-RPC error',
data: error.message
},
id: id
});
}
} else if (method === 'eth_gasPrice') {
console.log('Handling eth_gasPrice method');
// Implementasi untuk mengembalikan gas price(bebas tetapi lebih baik gunkan konversi gwei)., misalnya:
res.json({
jsonrpc: '2.0',
result: '0x12a05f200', // Contoh gas price dalam format heksadesimal
id: id
});
} else if (method === 'eth_estimateGas') {
console.log('Handling eth_estimateGas method');
// Implementasi untuk menghitung estimate gas, misalnya:
res.json({
jsonrpc: '2.0',
result: '0x5208', // Contoh estimate gas dalam format heksadesimal
id: id
});
} else if (method === 'eth_getTransactionCount') {
console.log('Handling eth_getTransactionCount method');
const [address, block] = params;
// Implementasi untuk mengembalikan transaction count, misalnya:
res.json({
jsonrpc: '2.0',
result: '0x1', // Contoh transaction count dalam format heksadesimal
id: id
});
}
});
app.listen(8000, () => {
console.log('Server HTTP berjalan di port 8000');
});

14
walet.json.bak Normal file
View File

@ -0,0 +1,14 @@
{
"wallets": [
{
"address": "0x12c102209cab0cfabcea3aff61674f8975bfae92",
"privateKey": "0x0de68fda60c58ec5693ab452654a4ab290fa256d635d4c34ee4853ee2c8ef747",
"balance": "0x13e8"
},
{
"address": "0xbb1bc791fa66c36f1e5e591bd87dd1b57185ffcc",
"privateKey": "0xd9adbf80713e940e7f2b2ee5b114a39cc567e53c8b06bf05c5df609a88b58e32",
"balance": "0x200001000"
}
]
}

14
wallets.json Normal file
View File

@ -0,0 +1,14 @@
{
"wallets": [
{
"address": "0xa10ca73a5dceafaaf54923aaf300ded8e0ce516b",
"privateKey": "0xc52cc54a42171674cbb45efa9fb8d98a9b54015c3ea503f5ed8ef7f54817046f",
"balance": "204fce5e3e25026110000000"
},
{
"address": "0x91379f8cf6dcf90ce08fe02d8de7cffd8f92d68e",
"privateKey": "0x8218a22ca9646f5fdc1cef4dc09c0c2fb015fd0092db35a08dcd9d90a4b9b81f",
"balance": "0x0"
}
]
}