Skip to content

Commit c237956

Browse files
committed
feat(dgeth): init prototype
1 parent 93a2b83 commit c237956

File tree

9 files changed

+982
-1377
lines changed

9 files changed

+982
-1377
lines changed

package-lock.json

Lines changed: 44 additions & 1365 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "dgeth",
3-
"version": "0.0.0",
3+
"version": "0.0.1",
44
"private": true,
5-
"description": "",
5+
"description": "Go-Ethereum Backing Provider",
66
"repository": {
77
"type": "git",
88
"url": "git+https://github.com/sambacha/dgeth.git"
99
},
1010
"keywords": [],
11-
"author": "sam bacha",
11+
"author": "SEE CONTRIBUTORS",
1212
"license": "SEE LICENSE IN LICENSE",
1313
"bugs": {
1414
"url": "https://github.com/sambacha/dgeth/issues"
@@ -19,9 +19,9 @@
1919
"types": "dist/esm/index.d.ts",
2020
"scripts": {
2121
"prepublishOnly": "yarn build",
22-
"test": "mocha",
23-
"lint": "eslint '{src,test}/**/*.ts'",
24-
"lint:fix": "eslint --fix '{src,test}/**/*.ts'",
22+
"test": "npx mocha",
23+
"lint": "npx eslint '{src,test}/**/*.ts'",
24+
"lint:fix": "npx eslint --fix '{src,test}/**/*.ts'",
2525
"build": "rimraf ./dist && yarn build:esm && yarn build:cjs",
2626
"build:esm": "tsc -p tsconfig.build.json --outDir dist/esm --module ES6",
2727
"build:cjs": "tsc -p tsconfig.build.json --outDir dist/cjs --declaration false",
@@ -38,7 +38,9 @@
3838
"@types/node": "^16",
3939
"@types/verror": "^1.10.5",
4040
"ethers": "^5.6.8",
41+
"bindings": "~1.2.1",
4142
"ffi-napi": "^4.0.3",
43+
"node-addon-api": "^4.2.0",
4244
"verror": "^1.10.1"
4345
},
4446
"devDependencies": {
@@ -56,8 +58,13 @@
5658
"process-tracing": "^1.0.2",
5759
"sinon": "^14.0.0",
5860
"sinon-chai": "^3.7.0",
59-
"ts-node": "^10.8.1",
61+
"ts-node": "^10.9.1",
6062
"typescript": "4.6.3",
61-
"typescript-eslint-language-service": "^5.0.0"
62-
}
63+
"typescript-eslint-language-service": "^5.0.0",
64+
"@ethereum-waffle/chai": "^3.4.0",
65+
"@swc-node/register": "^1.4.2",
66+
"@types/ffi-napi": "^4.0.4",
67+
"node-gyp": "^8.4.1"
68+
},
69+
"gypfile": true
6370
}

rust/build.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ fn main() {
99
}
1010

1111
fn c_bindgen() {
12-
//let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
12+
1313
println!("cargo:rerun-if-changed=wrapper.h");
1414
let bindings = bindgen::Builder::default()
1515
.header("wrapper.h")
1616
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
1717

1818
.generate()
19-
.expect("Unable to generate bindings");
19+
.expect("Err.Unable to generate bindings");
2020
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
2121
bindings
2222
.write_to_file(out_path.join("bindings.rs"))
23-
.expect("Unable to write bindings");
23+
.expect("Err.Unable to write bindings");
2424
}

src/DGethProvider.ts

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
import { assert } from 'chai';
2+
import {BigNumber, BigNumberish, providers, utils} from 'ethers';
3+
import { BlockWithTransactions} from '@ethersproject/abstract-provider';
4+
import {Simulator} from './simulator';
5+
6+
async function noBlockTag(blockTag: any) {
7+
if (await blockTag) {
8+
throw new Error('🟥 Not implemented: blockTag');
9+
}
10+
}
11+
12+
export class DGethProvider extends providers.Provider {
13+
sim: Simulator
14+
15+
constructor() {
16+
super();
17+
this.sim = new Simulator();
18+
}
19+
20+
async call(
21+
transaction: utils.Deferrable<providers.TransactionRequest>,
22+
blockTag?: providers.BlockTag | Promise<providers.BlockTag>
23+
): Promise<string> {
24+
await noBlockTag(blockTag);
25+
const tx = await utils.resolveProperties(transaction)
26+
27+
assert(tx.to, 'transaction.to is required');
28+
return this.sim.call({
29+
from: tx.from,
30+
to: tx.to!,
31+
gas: tx.gasLimit ? BigNumber.from(tx.gasLimit).toNumber() : undefined,
32+
gasPrice: tx.gasPrice ? BigNumber.from(tx.gasPrice).toHexString() : undefined,
33+
// gasFeeCap: BigNumber.from(tx.gasFeeCap).toHexString(),
34+
// gasTipCap: BigNumber.from(tx.gasTipCap).toHexString(),
35+
value: tx.value ? BigNumber.from(tx.value).toHexString() : undefined,
36+
data: tx.data ? BigNumber.from(tx.data).toHexString() : undefined,
37+
})!;
38+
}
39+
40+
emit(eventName: providers.EventType, ...args: Array<any>): boolean {
41+
throw new Error('🟥 Not implemented');
42+
}
43+
44+
estimateGas(transaction: utils.Deferrable<providers.TransactionRequest>): Promise<BigNumber> {
45+
throw new Error('🟥 Not implemented');
46+
}
47+
48+
async getBalance(
49+
addressOrName: string | Promise<string>,
50+
blockTag?: providers.BlockTag | Promise<providers.BlockTag>
51+
): Promise<BigNumber> {
52+
await noBlockTag(blockTag);
53+
const address = await addressOrName;
54+
if (!utils.isAddress(address)) {
55+
throw new Error('🟥 Not implemented: ENS');
56+
}
57+
return BigNumber.from(this.sim.getBalance(address));
58+
}
59+
60+
async getBlock(blockHashOrBlockTag: providers.BlockTag | string | Promise<providers.BlockTag | string>): Promise<providers.Block> {
61+
const block = this.sim.getBlock((await blockHashOrBlockTag).toString())
62+
const difficulty = BigNumber.from(block.difficulty)
63+
return {
64+
transactions: [], // TODO
65+
difficulty: difficulty.toNumber(),
66+
_difficulty: difficulty,
67+
extraData: '',
68+
gasLimit: BigNumber.from(block.gasLimit),
69+
gasUsed: BigNumber.from(block.gasUsed),
70+
hash: block.hash,
71+
miner: block.miner,
72+
nonce: block.nonce,
73+
number: BigNumber.from(block.number).toNumber(),
74+
parentHash: block.parentHash,
75+
timestamp: BigNumber.from(block.timestamp).toNumber(),
76+
baseFeePerGas: BigNumber.from(block.baseFeePerGas)
77+
}
78+
}
79+
80+
getBlockNumber(): Promise<number> {
81+
return Promise.resolve(Number.parseInt(this.sim.getBlockNumber()));
82+
}
83+
84+
getBlockWithTransactions(
85+
blockHashOrBlockTag: providers.BlockTag | string | Promise<providers.BlockTag | string>
86+
): Promise<BlockWithTransactions> {
87+
throw new Error('🟥 Not implemented');
88+
}
89+
90+
async getCode(addressOrName: string | Promise<string>, blockTag?: providers.BlockTag | Promise<providers.BlockTag>): Promise<string> {
91+
return this.sim.getCode(await addressOrName);
92+
}
93+
94+
async getGasPrice(): Promise<BigNumber> {
95+
return BigNumber.from(8000000);
96+
}
97+
98+
async getLogs(filter: providers.Filter): Promise<providers.Log[]> {
99+
throw new Error('🟥 Not implemented');
100+
}
101+
102+
getNetwork(): Promise<providers.Network> {
103+
const network: providers.Network = {
104+
name: 'undefined',
105+
chainId: Number.parseInt(this.sim.getChainID())
106+
};
107+
return Promise.resolve(network);
108+
}
109+
110+
getStorageAt(
111+
addressOrName: string | Promise<string>,
112+
position: BigNumberish | Promise<BigNumberish>,
113+
blockTag?: providers.BlockTag | Promise<providers.BlockTag>
114+
): Promise<string> {
115+
throw new Error('🟥 Not implemented');
116+
}
117+
118+
async getTransaction(transactionHash: string): Promise<providers.TransactionResponse> {
119+
const {Tx} = this.sim.getTransaction(transactionHash);
120+
return {
121+
hash: Tx.hash,
122+
to: Tx.to,
123+
nonce: Number.parseInt(Tx.nonce, 16),
124+
125+
gasLimit: BigNumber.from(Tx.gas),
126+
// TODO
127+
// gasPrice: BigNumber.from(Tx.gasPrice),
128+
129+
data: Tx.input,
130+
value: BigNumber.from(Tx.value),
131+
chainId: Number.parseInt(this.sim.getChainID(), 16),
132+
133+
// TODO
134+
// r: Tx.r,
135+
// s: Tx.s,
136+
// v: Tx.v,
137+
138+
confirmations: 0,
139+
from: '0x',
140+
wait: () => { throw new Error('🟥 Not implemented'); }
141+
};
142+
}
143+
144+
async getTransactionCount(
145+
addressOrName: string | Promise<string>,
146+
blockTag?: providers.BlockTag | Promise<providers.BlockTag>
147+
): Promise<number> {
148+
return this.sim.getTransactionCount(await addressOrName);
149+
}
150+
151+
getTransactionReceipt(transactionHash: string): Promise<providers.TransactionReceipt> {
152+
throw new Error('🟥 Not implemented');
153+
}
154+
155+
listenerCount(eventName?: providers.EventType): number {
156+
throw new Error('🟥 Not implemented');
157+
}
158+
159+
listeners(eventName?: providers.EventType): Array<providers.Listener> {
160+
throw new Error('🟥 Not implemented');
161+
}
162+
163+
lookupAddress(address: string | Promise<string>): Promise<string> {
164+
throw new Error('🟥 Not implemented');
165+
}
166+
167+
off(eventName: providers.EventType, listener?: providers.Listener): providers.Provider {
168+
throw new Error('🟥 Not implemented');
169+
}
170+
171+
on(eventName: providers.EventType, listener: providers.Listener): providers.Provider {
172+
throw new Error('🟥 Not implemented');
173+
}
174+
175+
once(eventName: providers.EventType, listener: providers.Listener): providers.Provider;
176+
once(eventName: 'block', handler: () => void): void;
177+
once(eventName: providers.EventType | 'block', listener: providers.Listener | (() => void)): providers.Provider | void {
178+
throw new Error('🟥 Not implemented');
179+
}
180+
181+
removeAllListeners(eventName?: providers.EventType): providers.Provider {
182+
throw new Error('🟥 Not implemented');
183+
}
184+
185+
async resolveName(name: string | Promise<string>): Promise<string> {
186+
return name;
187+
}
188+
189+
async sendTransaction(signedTransaction: string | Promise<string>): Promise<providers.TransactionResponse> {
190+
const data = await signedTransaction;
191+
const receipt = this.sim.sendTransaction(data)
192+
193+
// https://docs.ethers.io/v5/api/providers/types/#providers-TransactionReceipt
194+
const ethersReceipt: providers.TransactionReceipt & providers.TransactionResponse = {
195+
196+
to: receipt.to === '' ? null as any : receipt.to,
197+
from: receipt.from,
198+
nonce: 0, // TODO
199+
200+
gasLimit: BigNumber.from(0), // TODO
201+
gasPrice: BigNumber.from(0), // TODO
202+
203+
data: '0x', // TODO
204+
value: BigNumber.from(0), // TODO
205+
chainId: 1337, // TODO
206+
207+
// r?: string,
208+
// s?: string,
209+
// v?: number,
210+
211+
// Typed-Transaction features
212+
// type?: number | null,
213+
214+
// EIP-2930; Type 1 & EIP-1559; Type 2
215+
// accessList?: AccessList,
216+
217+
// EIP-1559; Type 2
218+
// maxPriorityFeePerGas?: BigNumber,
219+
// maxFeePerGas?: BigNumber,
220+
hash: receipt.txHash,
221+
222+
// Only if a transaction has been mined
223+
blockNumber: BigNumber.from(receipt.blockNumber).toNumber(),
224+
blockHash: receipt.blockHash,
225+
// timestamp?: number,
226+
227+
confirmations: 1,
228+
229+
// 🟥 Not optional (as it is in Transaction)
230+
231+
// The raw transaction
232+
raw: data,
233+
234+
// This function waits until the transaction has been mined
235+
wait: async (confirmations?: number) => ethersReceipt,
236+
237+
238+
contractAddress: receipt.contractAddress,
239+
transactionIndex: receipt.transactionIndex,
240+
// root?: string,
241+
gasUsed: BigNumber.from(receipt.gasUsed),
242+
logsBloom: 'TODO',
243+
transactionHash: receipt.txHash,
244+
logs: [], // TODO
245+
cumulativeGasUsed: BigNumber.from(receipt.cumulativeGasUsed),
246+
effectiveGasPrice: BigNumber.from(10000), // TODO
247+
byzantium: true,
248+
type: receipt.type,
249+
status: receipt.status,
250+
};
251+
252+
return ethersReceipt;
253+
}
254+
255+
waitForTransaction(transactionHash: string, confirmations?: number, timeout?: number): Promise<providers.TransactionReceipt> {
256+
throw new Error('🟥 Not implemented');
257+
}
258+
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './dgeth';
22
export * from './native';
33
export * from './regex';
44
export * from './types';
5+
export * from './DGethProvider';

0 commit comments

Comments
 (0)