@leofcoin/peernet 1.1.79 → 1.1.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.esdoc.json +10 -10
  2. package/.gitattributes +2 -2
  3. package/.prettierrc +7 -7
  4. package/.travis.yml +27 -27
  5. package/BREAKING_CHANGES.md +34 -34
  6. package/LICENSE +21 -21
  7. package/README.md +72 -72
  8. package/deploy.js +8 -8
  9. package/exports/browser/{browser-WUe24rfW.js → browser-DQJ6xf_F.js} +3 -3
  10. package/exports/browser/browser-store.js +168 -22
  11. package/exports/browser/{client-I9x7CFr1.js → client-C0VVXIWm.js} +66 -32
  12. package/exports/browser/{peernet-DULgegxE.js → identity-CQ_ieRiz.js} +2232 -13425
  13. package/exports/browser/identity.d.ts +1 -1
  14. package/exports/browser/identity.js +1 -0
  15. package/exports/browser/{index-sw14JvKD.js → index-BeqbCwUk.js} +1 -2
  16. package/exports/browser/{index-In1Jzp-v.js → index-CEwkDK9g.js} +10 -489
  17. package/exports/browser/{messages-lzTD4EMU.js → messages-BdevLRCA.js} +167 -166
  18. package/exports/browser/peernet-DEIKLS2i.js +13220 -0
  19. package/exports/browser/peernet.d.ts +7 -7
  20. package/exports/browser/peernet.js +3 -2
  21. package/exports/identity.js +92 -0
  22. package/exports/{messages-T3M-Ff1E.js → messages-BmpgEM4y.js} +163 -163
  23. package/exports/peernet.js +189 -273
  24. package/exports/src/prompts/password.js +3 -3
  25. package/exports/store.js +9 -2
  26. package/exports/types/identity.d.ts +1 -1
  27. package/exports/types/peernet.d.ts +7 -7
  28. package/index.html +19 -19
  29. package/package.json +71 -62
  30. package/rollup.config.js +63 -63
  31. package/src/dht/dht.ts +147 -147
  32. package/src/discovery/peer-discovery.js +75 -75
  33. package/src/errors/errors.js +12 -12
  34. package/src/handlers/data.js +15 -15
  35. package/src/handlers/message.js +34 -34
  36. package/src/identity.ts +104 -104
  37. package/src/messages/chat.js +13 -13
  38. package/src/messages/data-response.js +13 -13
  39. package/src/messages/data.js +17 -17
  40. package/src/messages/dht-response.js +13 -13
  41. package/src/messages/dht.js +21 -21
  42. package/src/messages/file-link.js +17 -17
  43. package/src/messages/file.js +17 -17
  44. package/src/messages/peer-response.js +13 -13
  45. package/src/messages/peer.js +13 -13
  46. package/src/messages/peernet.js +13 -13
  47. package/src/messages/ps.js +13 -13
  48. package/src/messages/request.js +13 -13
  49. package/src/messages/response.js +13 -13
  50. package/src/messages.js +13 -13
  51. package/src/peer-info.js +9 -9
  52. package/src/peernet.ts +817 -817
  53. package/src/prompts/password/browser.js +1 -1
  54. package/src/prompts/password/node.js +6 -6
  55. package/src/proto/chat-message.proto.js +6 -6
  56. package/src/proto/data-response.proto.js +4 -4
  57. package/src/proto/data.proto.js +4 -4
  58. package/src/proto/dht-response.proto.js +4 -4
  59. package/src/proto/dht.proto.js +4 -4
  60. package/src/proto/file-link.proto.js +5 -5
  61. package/src/proto/file.proto.js +5 -5
  62. package/src/proto/peer-response.proto.js +3 -3
  63. package/src/proto/peer.proto.js +3 -3
  64. package/src/proto/peernet.proto.js +7 -7
  65. package/src/proto/ps.proto.js +4 -4
  66. package/src/proto/request.proto.js +4 -4
  67. package/src/proto/response.proto.js +3 -3
  68. package/src/types.ts +25 -25
  69. package/src/utils/utils.js +77 -77
  70. package/test/client.js +14 -14
  71. package/test/codec.js +56 -56
  72. package/test/hash.js +13 -13
  73. package/test/index.js +3 -3
  74. package/test/lastBlock.js +7 -7
  75. package/test/messages.js +26 -26
  76. package/test/peernet.js +17 -17
  77. package/test/peernet.test.js +159 -0
  78. package/test.js +62 -62
  79. package/test2.js +13 -13
  80. package/test3.js +15 -15
  81. package/test4.js +7 -7
  82. package/tsconfig.json +11 -13
  83. /package/exports/browser/{browser-AyxSBUXj.js → browser-pguCHlVu.js} +0 -0
  84. /package/exports/browser/{qr-scanner-worker.min-RaSiJc_R.js → qr-scanner-worker.min-Dy0qkKA4.js} +0 -0
  85. /package/exports/browser/{value-wzPYMxsX.js → value-C3vAp-wb.js} +0 -0
package/package.json CHANGED
@@ -1,62 +1,71 @@
1
- {
2
- "name": "@leofcoin/peernet",
3
- "version": "1.1.79",
4
- "description": "",
5
- "browser": "./exports/browser/peernet.js",
6
- "exports": {
7
- ".": {
8
- "import": "./exports/peernet.js",
9
- "require": "./exports/commonjs/peernet.js",
10
- "types": "./exports/types/peernet.d.ts"
11
- },
12
- "./browser": "./exports/browser/peernet.js"
13
- },
14
- "type": "module",
15
- "engines": {
16
- "node": ">=19.0.0"
17
- },
18
- "scripts": {
19
- "build": "rollup -c",
20
- "watch": "rollup -c -w",
21
- "test": "node test/index.js",
22
- "server": "discovery-swarm-webrtc --port=4000",
23
- "demo": "jsproject --serve ./ --port 6868"
24
- },
25
- "keywords": [],
26
- "author": "",
27
- "license": "MIT",
28
- "dependencies": {
29
- "@leofcoin/codec-format-interface": "^1.6.0",
30
- "@leofcoin/codecs": "^1.0.0",
31
- "@leofcoin/generate-account": "^2.0.0",
32
- "@leofcoin/identity-utils": "^1.0.2",
33
- "@leofcoin/multi-wallet": "^3.1.4",
34
- "@leofcoin/storage": "^3.0.0",
35
- "@netpeer/p2pt-swarm": "^1.3.5",
36
- "@netpeer/swarm": "^0.8.1",
37
- "@vandeurenglenn/base32": "^1.1.0",
38
- "@vandeurenglenn/base58": "^1.1.0",
39
- "@vandeurenglenn/debug": "^1.0.0",
40
- "@vandeurenglenn/is-hex": "^1.0.0",
41
- "@vandeurenglenn/little-pubsub": "^1.3.1",
42
- "inquirer": "^9.1.4",
43
- "multi-signature": "^1.3.1",
44
- "qr-scanner": "^1.4.2",
45
- "qrcode": "^1.5.1",
46
- "socket-request-client": "^2.0.6",
47
- "socket-request-server": "^1.6.6"
48
- },
49
- "devDependencies": {
50
- "@rollup/plugin-commonjs": "^25.0.7",
51
- "@rollup/plugin-json": "^6.1.0",
52
- "@rollup/plugin-node-resolve": "^15.2.3",
53
- "@rollup/plugin-typescript": "^11.1.6",
54
- "@rollup/plugin-wasm": "^6.2.2",
55
- "@types/bs58check": "^2.1.0",
56
- "@types/node": "^20.11.0",
57
- "@types/qrcode": "^1.5.2",
58
- "@types/secp256k1": "^4.0.3",
59
- "@types/varint": "^6.0.1",
60
- "rollup": "^4.9.4"
61
- }
62
- }
1
+ {
2
+ "name": "@leofcoin/peernet",
3
+ "version": "1.1.81",
4
+ "description": "",
5
+ "browser": "./exports/browser/peernet.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./exports/peernet.js",
9
+ "require": "./exports/commonjs/peernet.js",
10
+ "types": "./exports/types/peernet.d.ts"
11
+ },
12
+ "./identity": {
13
+ "import": "./exports/identity.js",
14
+ "require": "./exports/commonjs/identity.js",
15
+ "types": "./exports/types/identity.d.ts"
16
+ },
17
+ "./browser": "./exports/browser/peernet.js"
18
+ },
19
+ "type": "module",
20
+ "engines": {
21
+ "node": ">=19.0.0"
22
+ },
23
+ "scripts": {
24
+ "build": "rollup -c",
25
+ "watch": "rollup -c -w",
26
+ "test": "npx mocha test/peernet.test.ts",
27
+ "server": "discovery-swarm-webrtc --port=4000",
28
+ "demo": "jsproject --serve ./ --port 6868"
29
+ },
30
+ "keywords": [],
31
+ "author": "",
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "@leofcoin/codec-format-interface": "^1.7.11",
35
+ "@leofcoin/codecs": "^1.0.6",
36
+ "@leofcoin/generate-account": "^2.0.3",
37
+ "@leofcoin/identity-utils": "^1.0.2",
38
+ "@leofcoin/multi-wallet": "^3.1.8",
39
+ "@leofcoin/storage": "^3.5.32",
40
+ "@netpeer/p2pt-swarm": "^1.3.6",
41
+ "@netpeer/swarm": "^0.8.16",
42
+ "@vandeurenglenn/base32": "^1.2.4",
43
+ "@vandeurenglenn/base58": "^1.1.9",
44
+ "@vandeurenglenn/debug": "^1.2.5",
45
+ "@vandeurenglenn/is-hex": "^1.1.1",
46
+ "@vandeurenglenn/little-pubsub": "^1.5.1",
47
+ "inquirer": "^10.2.2",
48
+ "multi-signature": "^1.3.1",
49
+ "qr-scanner": "^1.4.2",
50
+ "qrcode": "^1.5.4",
51
+ "socket-request-client": "^2.0.9",
52
+ "socket-request-server": "^1.6.17"
53
+ },
54
+ "devDependencies": {
55
+ "@jest/globals": "^29.7.0",
56
+ "@rollup/plugin-commonjs": "^26.0.1",
57
+ "@rollup/plugin-json": "^6.1.0",
58
+ "@rollup/plugin-node-resolve": "^15.2.3",
59
+ "@rollup/plugin-typescript": "^11.1.6",
60
+ "@rollup/plugin-wasm": "^6.2.2",
61
+ "@types/bs58check": "^2.1.2",
62
+ "@types/node": "^22.5.5",
63
+ "@types/qrcode": "^1.5.5",
64
+ "@types/secp256k1": "^4.0.6",
65
+ "@types/varint": "^6.0.3",
66
+ "chai": "^5.1.1",
67
+ "cross-env": "^7.0.3",
68
+ "rollup": "^4.21.3",
69
+ "sinon": "^19.0.2"
70
+ }
71
+ }
package/rollup.config.js CHANGED
@@ -1,63 +1,63 @@
1
- import resolve from '@rollup/plugin-node-resolve'
2
- import commonjs from '@rollup/plugin-commonjs'
3
- import json from '@rollup/plugin-json'
4
- import wasm from '@rollup/plugin-wasm'
5
- import rimraf from 'rimraf'
6
- import typescript from '@rollup/plugin-typescript'
7
-
8
- rimraf.sync('./exports/**')
9
-
10
- export default [
11
- {
12
- input: ['./src/peernet.ts', './node_modules/@leofcoin/storage/exports/browser-store.js'],
13
- output: {
14
- format: 'es',
15
- dir: './exports/browser'
16
- },
17
- plugins: [
18
- json(),
19
- wasm(),
20
- resolve({
21
- browser: true,
22
- preferBuiltins: false,
23
- mainFields: ['browser', 'module', 'main']
24
- }),
25
- commonjs({
26
- mainFields: ['browser', 'module', 'main']
27
- }),
28
-
29
- typescript({ compilerOptions: { outDir: './exports/browser' } })
30
- ],
31
- external: ['./prompts/password.js']
32
- },
33
- {
34
- input: ['./src/peernet.ts', './node_modules/@leofcoin/storage/exports/store.js'],
35
- output: {
36
- format: 'es',
37
- dir: './exports'
38
- },
39
- plugins: [
40
- typescript({
41
- compilerOptions: {
42
- outDir: './exports',
43
- declarationDir: './exports/types'
44
- }
45
- })
46
- ],
47
- external: ['./prompts/password.js']
48
- },
49
- {
50
- input: ['./src/prompts/password/browser.js'],
51
- output: {
52
- format: 'es',
53
- file: './exports/browser/src/prompts/password.js'
54
- }
55
- },
56
- {
57
- input: ['./src/prompts/password/node.js'],
58
- output: {
59
- format: 'es',
60
- file: './exports/src/prompts/password.js'
61
- }
62
- }
63
- ]
1
+ import resolve from '@rollup/plugin-node-resolve'
2
+ import commonjs from '@rollup/plugin-commonjs'
3
+ import json from '@rollup/plugin-json'
4
+ import wasm from '@rollup/plugin-wasm'
5
+ import rimraf from 'rimraf'
6
+ import typescript from '@rollup/plugin-typescript'
7
+
8
+ rimraf.sync('./exports/**')
9
+
10
+ export default [
11
+ {
12
+ input: ['./src/peernet.ts', './src/identity.ts', './node_modules/@leofcoin/storage/exports/browser-store.js'],
13
+ output: {
14
+ format: 'es',
15
+ dir: './exports/browser'
16
+ },
17
+ plugins: [
18
+ json(),
19
+ wasm(),
20
+ resolve({
21
+ browser: true,
22
+ preferBuiltins: false,
23
+ mainFields: ['browser', 'module', 'main']
24
+ }),
25
+ commonjs({
26
+ mainFields: ['browser', 'module', 'main']
27
+ }),
28
+
29
+ typescript({ compilerOptions: { outDir: './exports/browser' } })
30
+ ],
31
+ external: ['./prompts/password.js']
32
+ },
33
+ {
34
+ input: ['./src/peernet.ts', './src/identity.ts', './node_modules/@leofcoin/storage/exports/store.js'],
35
+ output: {
36
+ format: 'es',
37
+ dir: './exports'
38
+ },
39
+ plugins: [
40
+ typescript({
41
+ compilerOptions: {
42
+ outDir: './exports',
43
+ declarationDir: './exports/types'
44
+ }
45
+ })
46
+ ],
47
+ external: ['./prompts/password.js']
48
+ },
49
+ {
50
+ input: ['./src/prompts/password/browser.js'],
51
+ output: {
52
+ format: 'es',
53
+ file: './exports/browser/src/prompts/password.js'
54
+ }
55
+ },
56
+ {
57
+ input: ['./src/prompts/password/node.js'],
58
+ output: {
59
+ format: 'es',
60
+ file: './exports/src/prompts/password.js'
61
+ }
62
+ }
63
+ ]
package/src/dht/dht.ts CHANGED
@@ -1,147 +1,147 @@
1
- export declare type DHTProvider = {
2
- address: string
3
- id: string
4
- }
5
-
6
- export declare type DHTProviderDistanceResult = {
7
- provider: DHTProvider
8
- /**
9
- * distance on earth between peers in km
10
- */
11
- distance: number
12
- }
13
-
14
- export declare type DHTProviderMapValue = { [index: string]: DHTProvider }
15
-
16
- declare type Coordinates = {
17
- longitude: number
18
- latitude: number
19
- }
20
-
21
- /**
22
- * Keep history of fetched address and ptr
23
- * @property {Object} address
24
- * @property {Object} ptr
25
- */
26
- const lastFetched = {
27
- address: {
28
- value: undefined,
29
- timestamp: 0
30
- },
31
- ptr: {
32
- value: undefined,
33
- timestamp: 0
34
- }
35
- }
36
-
37
- const fetchedCoordinates = {}
38
-
39
- const getAddress = async () => {
40
- const { address } = lastFetched
41
- if (address) {
42
- address.value = await fetch('https://icanhazip.com/')
43
- address.value = await address.value.text()
44
- address.timestamp = Math.round(new Date().getTime() / 1000)
45
- lastFetched.address = address
46
- }
47
-
48
- return address.value
49
- }
50
-
51
- const degreesToRadians = (degrees) => {
52
- return (degrees * Math.PI) / 180
53
- }
54
-
55
- const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
56
- const earthRadiusKm = 6371
57
-
58
- const dLat = degreesToRadians(lat2 - lat1)
59
- const dLon = degreesToRadians(lon2 - lon1)
60
-
61
- lat1 = degreesToRadians(lat1)
62
- lat2 = degreesToRadians(lat2)
63
- const a =
64
- Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2)
65
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
66
- return earthRadiusKm * c
67
- }
68
-
69
- export default class DhtEarth {
70
- providerMap = new Map<string, DHTProviderMapValue>()
71
-
72
- /**
73
- *
74
- */
75
- constructor() {
76
- this.providerMap = new Map()
77
- }
78
-
79
- async getCoordinates(address: string): Promise<Coordinates> {
80
- if (!fetchedCoordinates[address]) {
81
- const request = `https://whereis.leofcoin.org/?ip=${address}`
82
- let response = await fetch(request)
83
- const { lat, lon } = (await response.json()) as { lat: number; lon: number }
84
- fetchedCoordinates[address] = { latitude: lat, longitude: lon }
85
- }
86
- return fetchedCoordinates[address]
87
- }
88
-
89
- /**
90
- * @param {Object} peer
91
- * @param {Object} provider
92
- * @return {Object} {provider, distance}
93
- */
94
- async getDistance(
95
- peer: { latitude: number; longitude: number },
96
- provider: DHTProvider
97
- ): Promise<DHTProviderDistanceResult> {
98
- const { latitude, longitude } = await this.getCoordinates(provider.address)
99
- return {
100
- provider,
101
- distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)
102
- }
103
- }
104
-
105
- async closestPeer(providers: Array<any>): Promise<DHTProvider> {
106
- let all = []
107
- const address = await getAddress()
108
- const peerLoc = await this.getCoordinates(address)
109
-
110
- for (const provider of providers) {
111
- if (provider.address === '127.0.0.1' || provider.address === '::1') all.push({ provider, distance: 0 })
112
- else all.push(this.getDistance(peerLoc, provider))
113
- }
114
-
115
- // todo queue
116
- all = await Promise.all(all)
117
- all = all.sort((previous, current) => previous.distance - current.distance)
118
- return all[0].provider
119
- }
120
-
121
- hasProvider(hash: string): boolean {
122
- return this.providerMap.has(hash)
123
- }
124
-
125
- providersFor(hash: string): DHTProviderMapValue {
126
- let providers: DHTProviderMapValue
127
- if (this.providerMap.has(hash)) providers = this.providerMap.get(hash)
128
- return providers
129
- }
130
-
131
- addProvider(provider: DHTProvider, hash: string) {
132
- let providers: DHTProviderMapValue = {}
133
- if (this.providerMap.has(hash)) {
134
- providers = this.providerMap.get(hash)
135
- }
136
- providers[provider.address] = provider
137
- this.providerMap.set(hash, providers)
138
- }
139
-
140
- removeProvider(address: string, hash: string) {
141
- if (this.providerMap.has(hash)) {
142
- const providers = this.providerMap.get(hash)
143
- delete providers[address]
144
- this.providerMap.set(hash, providers)
145
- }
146
- }
147
- }
1
+ export declare type DHTProvider = {
2
+ address: string
3
+ id: string
4
+ }
5
+
6
+ export declare type DHTProviderDistanceResult = {
7
+ provider: DHTProvider
8
+ /**
9
+ * distance on earth between peers in km
10
+ */
11
+ distance: number
12
+ }
13
+
14
+ export declare type DHTProviderMapValue = { [index: string]: DHTProvider }
15
+
16
+ declare type Coordinates = {
17
+ longitude: number
18
+ latitude: number
19
+ }
20
+
21
+ /**
22
+ * Keep history of fetched address and ptr
23
+ * @property {Object} address
24
+ * @property {Object} ptr
25
+ */
26
+ const lastFetched = {
27
+ address: {
28
+ value: undefined,
29
+ timestamp: 0
30
+ },
31
+ ptr: {
32
+ value: undefined,
33
+ timestamp: 0
34
+ }
35
+ }
36
+
37
+ const fetchedCoordinates = {}
38
+
39
+ const getAddress = async () => {
40
+ const { address } = lastFetched
41
+ if (address) {
42
+ address.value = await fetch('https://icanhazip.com/')
43
+ address.value = await address.value.text()
44
+ address.timestamp = Math.round(new Date().getTime() / 1000)
45
+ lastFetched.address = address
46
+ }
47
+
48
+ return address.value
49
+ }
50
+
51
+ const degreesToRadians = (degrees) => {
52
+ return (degrees * Math.PI) / 180
53
+ }
54
+
55
+ const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
56
+ const earthRadiusKm = 6371
57
+
58
+ const dLat = degreesToRadians(lat2 - lat1)
59
+ const dLon = degreesToRadians(lon2 - lon1)
60
+
61
+ lat1 = degreesToRadians(lat1)
62
+ lat2 = degreesToRadians(lat2)
63
+ const a =
64
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2)
65
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
66
+ return earthRadiusKm * c
67
+ }
68
+
69
+ export default class DhtEarth {
70
+ providerMap = new Map<string, DHTProviderMapValue>()
71
+
72
+ /**
73
+ *
74
+ */
75
+ constructor() {
76
+ this.providerMap = new Map()
77
+ }
78
+
79
+ async getCoordinates(address: string): Promise<Coordinates> {
80
+ if (!fetchedCoordinates[address]) {
81
+ const request = `https://whereis.leofcoin.org/?ip=${address}`
82
+ let response = await fetch(request)
83
+ const { lat, lon } = (await response.json()) as { lat: number; lon: number }
84
+ fetchedCoordinates[address] = { latitude: lat, longitude: lon }
85
+ }
86
+ return fetchedCoordinates[address]
87
+ }
88
+
89
+ /**
90
+ * @param {Object} peer
91
+ * @param {Object} provider
92
+ * @return {Object} {provider, distance}
93
+ */
94
+ async getDistance(
95
+ peer: { latitude: number; longitude: number },
96
+ provider: DHTProvider
97
+ ): Promise<DHTProviderDistanceResult> {
98
+ const { latitude, longitude } = await this.getCoordinates(provider.address)
99
+ return {
100
+ provider,
101
+ distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)
102
+ }
103
+ }
104
+
105
+ async closestPeer(providers: Array<any>): Promise<DHTProvider> {
106
+ let all = []
107
+ const address = await getAddress()
108
+ const peerLoc = await this.getCoordinates(address)
109
+
110
+ for (const provider of providers) {
111
+ if (provider.address === '127.0.0.1' || provider.address === '::1') all.push({ provider, distance: 0 })
112
+ else all.push(this.getDistance(peerLoc, provider))
113
+ }
114
+
115
+ // todo queue
116
+ all = await Promise.all(all)
117
+ all = all.sort((previous, current) => previous.distance - current.distance)
118
+ return all[0].provider
119
+ }
120
+
121
+ hasProvider(hash: string): boolean {
122
+ return this.providerMap.has(hash)
123
+ }
124
+
125
+ providersFor(hash: string): DHTProviderMapValue {
126
+ let providers: DHTProviderMapValue
127
+ if (this.providerMap.has(hash)) providers = this.providerMap.get(hash)
128
+ return providers
129
+ }
130
+
131
+ addProvider(provider: DHTProvider, hash: string) {
132
+ let providers: DHTProviderMapValue = {}
133
+ if (this.providerMap.has(hash)) {
134
+ providers = this.providerMap.get(hash)
135
+ }
136
+ providers[provider.address] = provider
137
+ this.providerMap.set(hash, providers)
138
+ }
139
+
140
+ removeProvider(address: string, hash: string) {
141
+ if (this.providerMap.has(hash)) {
142
+ const providers = this.providerMap.get(hash)
143
+ delete providers[address]
144
+ this.providerMap.set(hash, providers)
145
+ }
146
+ }
147
+ }