@railgun-community/waku-broadcaster-client-node 8.4.0 → 9.0.2
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.
- package/README.md +138 -14
- package/dist/fees/broadcaster-fee-cache.d.ts +5 -0
- package/dist/fees/broadcaster-fee-cache.js +71 -0
- package/dist/fees/broadcaster-fee-cache.js.map +1 -1
- package/dist/fees/handle-authorized-fees-message.d.ts +2 -0
- package/dist/fees/handle-authorized-fees-message.js +34 -0
- package/dist/fees/handle-authorized-fees-message.js.map +1 -0
- package/dist/fees/handle-fees-message.d.ts +1 -1
- package/dist/fees/handle-fees-message.js +42 -3
- package/dist/fees/handle-fees-message.js.map +1 -1
- package/dist/models/broadcaster-config.d.ts +13 -2
- package/dist/models/broadcaster-config.js +7 -0
- package/dist/models/broadcaster-config.js.map +1 -1
- package/dist/models/constants.d.ts +3 -1
- package/dist/models/constants.js +7 -11
- package/dist/models/constants.js.map +1 -1
- package/dist/models/export-models.d.ts +10 -0
- package/dist/models/export-models.js.map +1 -1
- package/dist/search/best-broadcaster.d.ts +2 -2
- package/dist/search/best-broadcaster.js +31 -4
- package/dist/search/best-broadcaster.js.map +1 -1
- package/dist/status/broadcaster-connection-status.js +2 -1
- package/dist/status/broadcaster-connection-status.js.map +1 -1
- package/dist/transact/broadcaster-transact-response.d.ts +1 -1
- package/dist/transact/broadcaster-transact-response.js.map +1 -1
- package/dist/transact/broadcaster-transaction.js +10 -1
- package/dist/transact/broadcaster-transaction.js.map +1 -1
- package/dist/utils/broadcaster-debug.js.map +1 -1
- package/dist/utils/broadcaster-util.js.map +1 -1
- package/dist/utils/is-defined.d.ts +1 -1
- package/dist/waku/waku-broadcaster-waku-core-base.d.ts +31 -0
- package/dist/waku/waku-broadcaster-waku-core-base.js +171 -0
- package/dist/waku/waku-broadcaster-waku-core-base.js.map +1 -0
- package/dist/waku/waku-broadcaster-waku-core.d.ts +3 -24
- package/dist/waku/waku-broadcaster-waku-core.js +33 -141
- package/dist/waku/waku-broadcaster-waku-core.js.map +1 -1
- package/dist/waku/waku-observers.d.ts +12 -4
- package/dist/waku/waku-observers.js +82 -36
- package/dist/waku/waku-observers.js.map +1 -1
- package/dist/waku-broadcaster-client.d.ts +4 -6
- package/dist/waku-broadcaster-client.js +22 -29
- package/dist/waku-broadcaster-client.js.map +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -1,22 +1,146 @@
|
|
|
1
|
-
# RAILGUN Broadcaster Client
|
|
1
|
+
# RAILGUN Broadcaster Client (Node.js)
|
|
2
2
|
|
|
3
|
-
This package is
|
|
3
|
+
The **Node.js** specific package for the RAILGUN Broadcaster Client. This package is designed to run in server-side environments, scripts, or bots that need to interact with the RAILGUN privacy network via Waku.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @railgun-community/waku-broadcaster-client-node
|
|
9
|
+
# or
|
|
10
|
+
npm install @railgun-community/waku-broadcaster-client-node
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### 1. Initialization
|
|
16
|
+
|
|
17
|
+
Initialize the client to connect to the Waku network.
|
|
8
18
|
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
19
|
+
```typescript
|
|
20
|
+
import { WakuBroadcasterClient } from '@railgun-community/waku-broadcaster-client-node';
|
|
21
|
+
import { Chain } from '@railgun-community/shared-models';
|
|
12
22
|
|
|
13
|
-
|
|
14
|
-
// Broadcasts fees through the privacy-safe Waku network.
|
|
23
|
+
const chain: Chain = { type: 0, id: 1 }; // Ethereum Mainnet
|
|
15
24
|
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
const broadcasterOptions = {
|
|
26
|
+
// Required: Trusted Fee Signer
|
|
27
|
+
trustedFeeSigner: '0zk1...',
|
|
28
|
+
// Optional: Waku options
|
|
29
|
+
pubSubTopic: '/waku/2/default-waku/proto',
|
|
30
|
+
feeExpirationTimeout: 30000, // 30 seconds
|
|
31
|
+
peerDiscoveryTimeout: 10000, // 10 seconds
|
|
32
|
+
additionalDirectPeers: [], // Optional: Direct peers to connect to
|
|
33
|
+
poiActiveListKeys: [], // Optional: POI keys
|
|
34
|
+
useDNSDiscovery: false, // Optional: Use DNS discovery
|
|
35
|
+
useCustomDNS: { // Optional: Custom DNS config
|
|
36
|
+
onlyCustom: false,
|
|
37
|
+
enrTreePeers: []
|
|
38
|
+
},
|
|
39
|
+
broadcasterVersionRange: { // Optional: Broadcaster version range
|
|
40
|
+
minVersion: '8.0.0',
|
|
41
|
+
maxVersion: '8.999.0'
|
|
42
|
+
}
|
|
43
|
+
};
|
|
18
44
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
45
|
+
const statusCallback = (status: BroadcasterConnectionStatus) => {
|
|
46
|
+
console.log('Connection status:', status);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
await WakuBroadcasterClient.start(chain, broadcasterOptions, statusCallback);
|
|
50
|
+
console.log('Waku Broadcaster Client started');
|
|
22
51
|
```
|
|
52
|
+
|
|
53
|
+
### 2. Finding a Broadcaster
|
|
54
|
+
|
|
55
|
+
Once started, the client listens for fee updates from Broadcasters. You can query for the best broadcaster for a specific token.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { Chain } from '@railgun-community/shared-models';
|
|
59
|
+
|
|
60
|
+
const chain: Chain = { type: 0, id: 1 }; // Ethereum Mainnet
|
|
61
|
+
const tokenAddress = '0x6b175474e89094c44da98b954eedeac495271d0f'; // DAI
|
|
62
|
+
|
|
63
|
+
// Wait a few seconds for peer discovery and fee updates...
|
|
64
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
65
|
+
|
|
66
|
+
const selectedBroadcaster = await WakuBroadcasterClient.findBestBroadcaster(
|
|
67
|
+
chain,
|
|
68
|
+
tokenAddress
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (selectedBroadcaster) {
|
|
72
|
+
console.log('Found broadcaster:', selectedBroadcaster.railgunAddress);
|
|
73
|
+
console.log('Fee per unit gas:', selectedBroadcaster.feePerUnitGas);
|
|
74
|
+
} else {
|
|
75
|
+
console.log('No broadcaster found for this token');
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. Sending a Transaction
|
|
80
|
+
|
|
81
|
+
Create a transaction and send it through the selected broadcaster.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { BroadcasterTransaction } from '@railgun-community/waku-broadcaster-client-node';
|
|
85
|
+
import { TXIDVersion } from '@railgun-community/shared-models';
|
|
86
|
+
|
|
87
|
+
// ... (Assume you have a railgunWallet and transactionRequest)
|
|
88
|
+
|
|
89
|
+
const txidVersion = TXIDVersion.V2_PoseidonMerkle; // or V3
|
|
90
|
+
const to = '0x...'; // Destination address
|
|
91
|
+
const data = '0x...'; // Transaction data
|
|
92
|
+
const nullifiers = ['0x...']; // Nullifiers
|
|
93
|
+
const overallBatchMinGasPrice = 1000000000n; // Min gas price
|
|
94
|
+
const useRelayAdapt = false; // Whether to use Relay Adapt
|
|
95
|
+
const preTransactionPOIs = {}; // POIs
|
|
96
|
+
|
|
97
|
+
const broadcasterTransaction = await BroadcasterTransaction.create(
|
|
98
|
+
txidVersion,
|
|
99
|
+
to,
|
|
100
|
+
data,
|
|
101
|
+
selectedBroadcaster.railgunAddress,
|
|
102
|
+
selectedBroadcaster.feesID,
|
|
103
|
+
chain,
|
|
104
|
+
nullifiers,
|
|
105
|
+
overallBatchMinGasPrice,
|
|
106
|
+
useRelayAdapt,
|
|
107
|
+
preTransactionPOIs
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const response = await BroadcasterTransaction.send(broadcasterTransaction);
|
|
112
|
+
console.log('Transaction submitted. Tx Hash:', response.txHash);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('Failed to send transaction:', error);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Configuration
|
|
119
|
+
|
|
120
|
+
The `start` method accepts a `BroadcasterOptions` object.
|
|
121
|
+
|
|
122
|
+
- `trustedFeeSigner`: (Required) The public key of the trusted fee signer.
|
|
123
|
+
- `poiActiveListKeys`: (Optional) List of active POI list keys.
|
|
124
|
+
- `pubSubTopic`: (Optional) The Waku pubsub topic to subscribe to. Defaults to the RAILGUN topic.
|
|
125
|
+
- `additionalDirectPeers`: (Optional) Array of multiaddrs for direct peer connections.
|
|
126
|
+
- `peerDiscoveryTimeout`: (Optional) Timeout in milliseconds for peer discovery.
|
|
127
|
+
- `feeExpirationTimeout`: (Optional) Timeout in milliseconds for fee expiration.
|
|
128
|
+
- `useDNSDiscovery`: (Optional) Boolean to enable DNS peer discovery.
|
|
129
|
+
- `useCustomDNS`: (Optional) Configuration for custom DNS discovery.
|
|
130
|
+
- `onlyCustom`: (Boolean) If true, only use the provided `enrTreePeers`.
|
|
131
|
+
- `enrTreePeers`: (Array<string>) List of ENR tree URLs.
|
|
132
|
+
- `broadcasterVersionRange`: (Optional) Object specifying the allowed broadcaster version range.
|
|
133
|
+
- `minVersion`: (String) Minimum allowed version.
|
|
134
|
+
- `maxVersion`: (String) Maximum allowed version.
|
|
135
|
+
|
|
136
|
+
## Dependencies
|
|
137
|
+
|
|
138
|
+
This package relies on:
|
|
139
|
+
- `@waku/sdk`: For Waku networking.
|
|
140
|
+
- `@waku/discovery`: For peer discovery.
|
|
141
|
+
- `@libp2p/tcp`: For TCP transport (Node.js specific).
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
146
|
+
|
|
@@ -13,6 +13,8 @@ export type BroadcasterFeeCacheState = {
|
|
|
13
13
|
};
|
|
14
14
|
export declare class BroadcasterFeeCache {
|
|
15
15
|
private static cache;
|
|
16
|
+
private static authorizedFees;
|
|
17
|
+
private static averageAuthorizedFees;
|
|
16
18
|
static lastSubscribedFeeMessageReceivedAt: Optional<number>;
|
|
17
19
|
private static poiActiveListKeys;
|
|
18
20
|
static init(poiActiveListKeys: string[]): void;
|
|
@@ -21,5 +23,8 @@ export declare class BroadcasterFeeCache {
|
|
|
21
23
|
static feesForChain(chain: Chain): Optional<BroadcasterFeeNetworkCacheMap>;
|
|
22
24
|
static feesForToken(chain: Chain, tokenAddress: string): Optional<BroadcasterFeeNetworkTokenCacheMap>;
|
|
23
25
|
static supportsToken(chain: Chain, tokenAddress: string, useRelayAdapt: boolean): boolean;
|
|
26
|
+
static addAuthorizedFees(signerAddress: string, tokenFeeMap: MapType<CachedTokenFee>): void;
|
|
27
|
+
private static updateAverageAuthorizedFees;
|
|
28
|
+
static getAuthorizedFee(tokenAddress: string): Optional<CachedTokenFee>;
|
|
24
29
|
}
|
|
25
30
|
export {};
|
|
@@ -5,6 +5,8 @@ import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
|
|
|
5
5
|
import { nameForBroadcaster, cachedFeeExpired, DEFAULT_BROADCASTER_IDENTIFIER, invalidBroadcasterVersion, cachedFeeUnavailableOrExpired, } from '../utils/broadcaster-util.js';
|
|
6
6
|
export class BroadcasterFeeCache {
|
|
7
7
|
static cache = { forNetwork: {} };
|
|
8
|
+
static authorizedFees = {};
|
|
9
|
+
static averageAuthorizedFees = {};
|
|
8
10
|
static lastSubscribedFeeMessageReceivedAt;
|
|
9
11
|
static poiActiveListKeys;
|
|
10
12
|
static init(poiActiveListKeys) {
|
|
@@ -80,5 +82,74 @@ export class BroadcasterFeeCache {
|
|
|
80
82
|
const availableUnexpiredFee = cachedFees.find(cachedFee => !cachedFeeUnavailableOrExpired(cachedFee, chain, useRelayAdapt));
|
|
81
83
|
return availableUnexpiredFee != null;
|
|
82
84
|
}
|
|
85
|
+
static addAuthorizedFees(signerAddress, tokenFeeMap) {
|
|
86
|
+
const newFees = Object.entries(tokenFeeMap);
|
|
87
|
+
const signerAddressLC = signerAddress.toLowerCase();
|
|
88
|
+
this.authorizedFees[signerAddressLC] ??= {};
|
|
89
|
+
const updatedTokens = [];
|
|
90
|
+
for (const [tokenAddress, feeMap] of newFees) {
|
|
91
|
+
const tokenAddressLC = tokenAddress.toLowerCase();
|
|
92
|
+
const existing = this.authorizedFees[signerAddressLC][tokenAddressLC];
|
|
93
|
+
if (existing && existing.expiration >= feeMap.expiration) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
this.authorizedFees[signerAddressLC][tokenAddressLC] = feeMap;
|
|
97
|
+
updatedTokens.push(tokenAddressLC);
|
|
98
|
+
}
|
|
99
|
+
this.updateAverageAuthorizedFees(updatedTokens);
|
|
100
|
+
}
|
|
101
|
+
static updateAverageAuthorizedFees(tokenAddresses) {
|
|
102
|
+
const trustedSigners = BroadcasterConfig.trustedFeeSigner;
|
|
103
|
+
const isTrustedSignerConfigured = trustedSigners != null &&
|
|
104
|
+
(typeof trustedSigners === 'string' || trustedSigners.length > 0);
|
|
105
|
+
tokenAddresses.forEach(tokenAddressLC => {
|
|
106
|
+
const authorizedFeesForToken = [];
|
|
107
|
+
Object.keys(this.authorizedFees).forEach(signerAddress => {
|
|
108
|
+
if (isTrustedSignerConfigured) {
|
|
109
|
+
if (typeof trustedSigners === 'string') {
|
|
110
|
+
if (signerAddress !== trustedSigners.toLowerCase()) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (Array.isArray(trustedSigners)) {
|
|
115
|
+
if (!trustedSigners
|
|
116
|
+
.map(s => s.toLowerCase())
|
|
117
|
+
.includes(signerAddress.toLowerCase())) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const fee = this.authorizedFees[signerAddress][tokenAddressLC];
|
|
123
|
+
if (fee) {
|
|
124
|
+
if (cachedFeeExpired(fee.expiration)) {
|
|
125
|
+
delete this.authorizedFees[signerAddress][tokenAddressLC];
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
authorizedFeesForToken.push(fee);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
if (authorizedFeesForToken.length === 0) {
|
|
132
|
+
delete this.averageAuthorizedFees[tokenAddressLC];
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (authorizedFeesForToken.length === 1) {
|
|
136
|
+
this.averageAuthorizedFees[tokenAddressLC] = authorizedFeesForToken[0];
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
let totalFee = 0n;
|
|
140
|
+
authorizedFeesForToken.forEach(fee => {
|
|
141
|
+
totalFee += BigInt(fee.feePerUnitGas);
|
|
142
|
+
});
|
|
143
|
+
const averageFee = totalFee / BigInt(authorizedFeesForToken.length);
|
|
144
|
+
const baseFee = authorizedFeesForToken[0];
|
|
145
|
+
this.averageAuthorizedFees[tokenAddressLC] = {
|
|
146
|
+
...baseFee,
|
|
147
|
+
feePerUnitGas: '0x' + averageFee.toString(16),
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
static getAuthorizedFee(tokenAddress) {
|
|
152
|
+
return this.averageAuthorizedFees[tokenAddress.toLowerCase()];
|
|
153
|
+
}
|
|
83
154
|
}
|
|
84
155
|
//# sourceMappingURL=broadcaster-fee-cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcaster-fee-cache.js","sourceRoot":"","sources":["../../src/fees/broadcaster-fee-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,GAChB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,8BAA8B,CAAC;AAgBtC,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAC,KAAK,GAA6B,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACpE,MAAM,CAAC,kCAAkC,CAAmB;IACpD,MAAM,CAAC,iBAAiB,CAAqB;IAErD,MAAM,CAAC,IAAI,CAAC,iBAA2B;QACrC,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,kCAAkC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,YAAY,CACjB,KAAY,EACZ,cAAsB,EACtB,aAAqB,EACrB,WAAoC,EACpC,UAA4B,EAC5B,OAAe,EACf,mBAA6B;QAE7B,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO;SACR;QAED,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAC3B,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;SACH;QACD,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE;YACzC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;gBAC7C,gBAAgB,CAAC,GAAG,CAClB,sBAAsB,cAAc,0BAA0B,OAAO,wBAAwB,CAC9F,CAAC;gBACF,OAAO;aACR;SACF;QAED,MAAM,eAAe,GAAG,kBAAkB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;QAEjC,IAAI,yBAAyB,CAAC,OAAO,CAAC,EAAE;YACtC,gBAAgB,CAAC,GAAG,CAClB,8BAA8B,OAAO,iBAAiB,iBAAiB,CAAC,2BAA2B,IAAI,iBAAiB,CAAC,2BAA2B,MAAM,eAAe,EAAE,CAC5K,CAAC;YACF,OAAO;SACR;QAED,IAAI,gBAAgB,CAAC,aAAa,CAAC,EAAE;YACnC,gBAAgB,CAAC,GAAG,CAClB,2BAA2B,WAAW,KAAK,eAAe,GAAG,CAC9D,CAAC;YACF,OAAO;SACR;QAED,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,gBAAgB,CAAC,GAAG,CAClB,4BAA4B,WAAW,KAAK,eAAe,MAAM,cAAc,CAAC,MAAM,SAAS,CAChG,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAExD,MAAM,uBAAuB,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAC3D,OAAO,CAAC,WAAW,EAAE,CACtB,CAAC;QACF,uBAAuB,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YAC7C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK;gBAC5D,cAAc,EAAE,EAAE;aACnB,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,cAAc,CACtE,cAAc,CACf,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;YAE5B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,cAAc,CACtE,cAAc,CACf,CAAC,aAAa,CAAC,UAAU,IAAI,8BAA8B,CAAC;gBAC3D,WAAW,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,mBAAmB,CAAC,kCAAkC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtE,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,KAAY;QAC5B,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO;SACR;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,KAAY;QAC9B,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;SACrC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,YAAY,CACjB,KAAY,EACZ,YAAoB;QAEpB,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,CAAC,aAAa,CAClB,KAAY,EACZ,YAAoB,EACpB,aAAsB;QAEtB,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,EAAE;YACjB,OAAO,KAAK,CAAC;SACd;QAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QAClE,MAAM,wBAAwB,GAAG,aAAa,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAExE,MAAM,UAAU,GAAqB,wBAAwB;aAC1D,GAAG,CAAC,cAAc,CAAC,EAAE,CACpB,MAAM,CAAC,MAAM,CACX,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,aAAa,CAC1D,CACF;aACA,IAAI,EAAE,CAAC;QAEV,MAAM,qBAAqB,GAAG,UAAU,CAAC,IAAI,CAC3C,SAAS,CAAC,EAAE,CACV,CAAC,6BAA6B,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC,CAClE,CAAC;QACF,OAAO,qBAAqB,IAAI,IAAI,CAAC;IACvC,CAAC","sourcesContent":["import {\n CachedTokenFee,\n Chain,\n networkForChain,\n} from '@railgun-community/shared-models';\nimport { AddressFilter } from '../filters/address-filter.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport {\n nameForBroadcaster,\n cachedFeeExpired,\n DEFAULT_BROADCASTER_IDENTIFIER,\n invalidBroadcasterVersion,\n cachedFeeUnavailableOrExpired,\n} from '../utils/broadcaster-util.js';\n\n// {forNetwork: {forToken: {forBroadcaster: (fee, updatedAt)}}}\ntype BroadcasterFeeNetworkTokenBroadcasterCacheMap = {\n forIdentifier: MapType<CachedTokenFee>;\n};\ntype BroadcasterFeeNetworkTokenCacheMap = {\n forBroadcaster: MapType<BroadcasterFeeNetworkTokenBroadcasterCacheMap>;\n};\ntype BroadcasterFeeNetworkCacheMap = {\n forToken: MapType<BroadcasterFeeNetworkTokenCacheMap>;\n};\nexport type BroadcasterFeeCacheState = {\n forNetwork: MapType<BroadcasterFeeNetworkCacheMap>;\n};\n\nexport class BroadcasterFeeCache {\n private static cache: BroadcasterFeeCacheState = { forNetwork: {} };\n static lastSubscribedFeeMessageReceivedAt: Optional<number>;\n private static poiActiveListKeys: Optional<string[]>;\n\n static init(poiActiveListKeys: string[]) {\n this.poiActiveListKeys = poiActiveListKeys;\n this.lastSubscribedFeeMessageReceivedAt = Date.now();\n }\n\n static addTokenFees(\n chain: Chain,\n railgunAddress: string,\n feeExpiration: number,\n tokenFeeMap: MapType<CachedTokenFee>,\n identifier: Optional<string>,\n version: string,\n requiredPOIListKeys: string[],\n ) {\n const network = networkForChain(chain);\n if (!network) {\n return;\n }\n\n if (!this.poiActiveListKeys) {\n throw new Error(\n 'Must define active POI list keys before adding any fees.',\n );\n }\n for (const listKey of requiredPOIListKeys) {\n if (!this.poiActiveListKeys.includes(listKey)) {\n BroadcasterDebug.log(\n `[Fees] Broadcaster ${railgunAddress} requires POI list key ${listKey}, which is not active.`,\n );\n return;\n }\n }\n\n const broadcasterName = nameForBroadcaster(railgunAddress, identifier);\n const networkName = network.name;\n\n if (invalidBroadcasterVersion(version)) {\n BroadcasterDebug.log(\n `[Fees] Broadcaster version ${version} invalid (req ${BroadcasterConfig.MINIMUM_BROADCASTER_VERSION}-${BroadcasterConfig.MAXIMUM_BROADCASTER_VERSION}): ${broadcasterName}`,\n );\n return;\n }\n\n if (cachedFeeExpired(feeExpiration)) {\n BroadcasterDebug.log(\n `[Fees] Fees expired for ${networkName} (${broadcasterName})`,\n );\n return;\n }\n\n const tokenAddresses = Object.keys(tokenFeeMap);\n BroadcasterDebug.log(\n `[Fees] Updating fees for ${networkName} (${broadcasterName}): ${tokenAddresses.length} tokens`,\n );\n\n this.cache.forNetwork[networkName] ??= { forToken: {} };\n\n const tokenAddressesLowercase = tokenAddresses.map(address =>\n address.toLowerCase(),\n );\n tokenAddressesLowercase.forEach(tokenAddress => {\n this.cache.forNetwork[networkName].forToken[tokenAddress] ??= {\n forBroadcaster: {},\n };\n this.cache.forNetwork[networkName].forToken[tokenAddress].forBroadcaster[\n railgunAddress\n ] ??= { forIdentifier: {} };\n\n this.cache.forNetwork[networkName].forToken[tokenAddress].forBroadcaster[\n railgunAddress\n ].forIdentifier[identifier ?? DEFAULT_BROADCASTER_IDENTIFIER] =\n tokenFeeMap[tokenAddress];\n });\n BroadcasterFeeCache.lastSubscribedFeeMessageReceivedAt = Date.now();\n }\n\n static resetCache(chain: Chain) {\n const network = networkForChain(chain);\n if (!network) {\n return;\n }\n this.cache.forNetwork ??= {};\n delete this.cache.forNetwork[network.name];\n }\n\n static feesForChain(chain: Chain): Optional<BroadcasterFeeNetworkCacheMap> {\n const network = networkForChain(chain);\n if (!network) {\n throw new Error('Chain not found.');\n }\n return this.cache.forNetwork[network.name];\n }\n\n static feesForToken(\n chain: Chain,\n tokenAddress: string,\n ): Optional<BroadcasterFeeNetworkTokenCacheMap> {\n return this.feesForChain(chain)?.forToken[tokenAddress.toLowerCase()];\n }\n\n static supportsToken(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n ): boolean {\n const feesForToken = this.feesForToken(chain, tokenAddress);\n if (!feesForToken) {\n return false;\n }\n\n const railgunAddresses = Object.keys(feesForToken.forBroadcaster);\n const filteredRailgunAddresses = AddressFilter.filter(railgunAddresses);\n\n const cachedFees: CachedTokenFee[] = filteredRailgunAddresses\n .map(railgunAddress =>\n Object.values(\n feesForToken.forBroadcaster[railgunAddress].forIdentifier,\n ),\n )\n .flat();\n\n const availableUnexpiredFee = cachedFees.find(\n cachedFee =>\n !cachedFeeUnavailableOrExpired(cachedFee, chain, useRelayAdapt),\n );\n return availableUnexpiredFee != null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"broadcaster-fee-cache.js","sourceRoot":"","sources":["../../src/fees/broadcaster-fee-cache.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CachedTokenFee,\n Chain,\n networkForChain,\n} from '@railgun-community/shared-models';\nimport { AddressFilter } from '../filters/address-filter.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport {\n nameForBroadcaster,\n cachedFeeExpired,\n DEFAULT_BROADCASTER_IDENTIFIER,\n invalidBroadcasterVersion,\n cachedFeeUnavailableOrExpired,\n} from '../utils/broadcaster-util.js';\n\n// {forNetwork: {forToken: {forBroadcaster: (fee, updatedAt)}}}\ntype BroadcasterFeeNetworkTokenBroadcasterCacheMap = {\n forIdentifier: MapType<CachedTokenFee>;\n};\ntype BroadcasterFeeNetworkTokenCacheMap = {\n forBroadcaster: MapType<BroadcasterFeeNetworkTokenBroadcasterCacheMap>;\n};\ntype BroadcasterFeeNetworkCacheMap = {\n forToken: MapType<BroadcasterFeeNetworkTokenCacheMap>;\n};\nexport type BroadcasterFeeCacheState = {\n forNetwork: MapType<BroadcasterFeeNetworkCacheMap>;\n};\n\nexport class BroadcasterFeeCache {\n private static cache: BroadcasterFeeCacheState = { forNetwork: {} };\n // signerAddress -> tokenAddress -> fee\n private static authorizedFees: MapType<MapType<CachedTokenFee>> = {};\n // tokenAddress -> fee (average)\n private static averageAuthorizedFees: MapType<CachedTokenFee> = {};\n static lastSubscribedFeeMessageReceivedAt: Optional<number>;\n private static poiActiveListKeys: Optional<string[]>;\n\n static init(poiActiveListKeys: string[]) {\n this.poiActiveListKeys = poiActiveListKeys;\n this.lastSubscribedFeeMessageReceivedAt = Date.now();\n }\n\n static addTokenFees(\n chain: Chain,\n railgunAddress: string,\n feeExpiration: number,\n tokenFeeMap: MapType<CachedTokenFee>,\n identifier: Optional<string>,\n version: string,\n requiredPOIListKeys: string[],\n ) {\n const network = networkForChain(chain);\n if (!network) {\n return;\n }\n\n if (!this.poiActiveListKeys) {\n throw new Error(\n 'Must define active POI list keys before adding any fees.',\n );\n }\n for (const listKey of requiredPOIListKeys) {\n if (!this.poiActiveListKeys.includes(listKey)) {\n BroadcasterDebug.log(\n `[Fees] Broadcaster ${railgunAddress} requires POI list key ${listKey}, which is not active.`,\n );\n return;\n }\n }\n\n const broadcasterName = nameForBroadcaster(railgunAddress, identifier);\n const networkName = network.name;\n\n if (invalidBroadcasterVersion(version)) {\n BroadcasterDebug.log(\n `[Fees] Broadcaster version ${version} invalid (req ${BroadcasterConfig.MINIMUM_BROADCASTER_VERSION}-${BroadcasterConfig.MAXIMUM_BROADCASTER_VERSION}): ${broadcasterName}`,\n );\n return;\n }\n\n if (cachedFeeExpired(feeExpiration)) {\n BroadcasterDebug.log(\n `[Fees] Fees expired for ${networkName} (${broadcasterName})`,\n );\n return;\n }\n\n const tokenAddresses = Object.keys(tokenFeeMap);\n BroadcasterDebug.log(\n `[Fees] Updating fees for ${networkName} (${broadcasterName}): ${tokenAddresses.length} tokens`,\n );\n\n this.cache.forNetwork[networkName] ??= { forToken: {} };\n\n const tokenAddressesLowercase = tokenAddresses.map(address =>\n address.toLowerCase(),\n );\n tokenAddressesLowercase.forEach(tokenAddress => {\n this.cache.forNetwork[networkName].forToken[tokenAddress] ??= {\n forBroadcaster: {},\n };\n this.cache.forNetwork[networkName].forToken[tokenAddress].forBroadcaster[\n railgunAddress\n ] ??= { forIdentifier: {} };\n\n this.cache.forNetwork[networkName].forToken[tokenAddress].forBroadcaster[\n railgunAddress\n ].forIdentifier[identifier ?? DEFAULT_BROADCASTER_IDENTIFIER] =\n tokenFeeMap[tokenAddress];\n });\n BroadcasterFeeCache.lastSubscribedFeeMessageReceivedAt = Date.now();\n }\n\n static resetCache(chain: Chain) {\n const network = networkForChain(chain);\n if (!network) {\n return;\n }\n this.cache.forNetwork ??= {};\n delete this.cache.forNetwork[network.name];\n }\n\n static feesForChain(chain: Chain): Optional<BroadcasterFeeNetworkCacheMap> {\n const network = networkForChain(chain);\n if (!network) {\n throw new Error('Chain not found.');\n }\n return this.cache.forNetwork[network.name];\n }\n\n static feesForToken(\n chain: Chain,\n tokenAddress: string,\n ): Optional<BroadcasterFeeNetworkTokenCacheMap> {\n return this.feesForChain(chain)?.forToken[tokenAddress.toLowerCase()];\n }\n\n static supportsToken(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n ): boolean {\n const feesForToken = this.feesForToken(chain, tokenAddress);\n if (!feesForToken) {\n return false;\n }\n\n const railgunAddresses = Object.keys(feesForToken.forBroadcaster);\n const filteredRailgunAddresses = AddressFilter.filter(railgunAddresses);\n\n const cachedFees: CachedTokenFee[] = filteredRailgunAddresses\n .map(railgunAddress =>\n Object.values(\n feesForToken.forBroadcaster[railgunAddress].forIdentifier,\n ),\n )\n .flat();\n\n const availableUnexpiredFee = cachedFees.find(\n cachedFee =>\n !cachedFeeUnavailableOrExpired(cachedFee, chain, useRelayAdapt),\n );\n return availableUnexpiredFee != null;\n }\n\n static addAuthorizedFees(\n signerAddress: string,\n tokenFeeMap: MapType<CachedTokenFee>,\n ) {\n const newFees = Object.entries(tokenFeeMap);\n const signerAddressLC = signerAddress.toLowerCase();\n this.authorizedFees[signerAddressLC] ??= {};\n\n const updatedTokens: string[] = [];\n\n for (const [tokenAddress, feeMap] of newFees) {\n const tokenAddressLC = tokenAddress.toLowerCase();\n const existing = this.authorizedFees[signerAddressLC][tokenAddressLC];\n if (existing && existing.expiration >= feeMap.expiration) {\n continue;\n }\n this.authorizedFees[signerAddressLC][tokenAddressLC] = feeMap;\n updatedTokens.push(tokenAddressLC);\n }\n this.updateAverageAuthorizedFees(updatedTokens);\n }\n\n private static updateAverageAuthorizedFees(tokenAddresses: string[]) {\n const trustedSigners = BroadcasterConfig.trustedFeeSigner;\n const isTrustedSignerConfigured =\n trustedSigners != null &&\n (typeof trustedSigners === 'string' || trustedSigners.length > 0);\n\n tokenAddresses.forEach(tokenAddressLC => {\n const authorizedFeesForToken: CachedTokenFee[] = [];\n\n Object.keys(this.authorizedFees).forEach(signerAddress => {\n if (isTrustedSignerConfigured) {\n if (typeof trustedSigners === 'string') {\n if (signerAddress !== trustedSigners.toLowerCase()) {\n return;\n }\n } else if (Array.isArray(trustedSigners)) {\n if (\n !trustedSigners\n .map(s => s.toLowerCase())\n .includes(signerAddress.toLowerCase())\n ) {\n return;\n }\n }\n }\n\n const fee = this.authorizedFees[signerAddress][tokenAddressLC];\n if (fee) {\n if (cachedFeeExpired(fee.expiration)) {\n delete this.authorizedFees[signerAddress][tokenAddressLC];\n return;\n }\n authorizedFeesForToken.push(fee);\n }\n });\n\n if (authorizedFeesForToken.length === 0) {\n delete this.averageAuthorizedFees[tokenAddressLC];\n return;\n }\n\n if (authorizedFeesForToken.length === 1) {\n this.averageAuthorizedFees[tokenAddressLC] = authorizedFeesForToken[0];\n return;\n }\n\n let totalFee = 0n;\n authorizedFeesForToken.forEach(fee => {\n totalFee += BigInt(fee.feePerUnitGas);\n });\n const averageFee = totalFee / BigInt(authorizedFeesForToken.length);\n\n const baseFee = authorizedFeesForToken[0];\n this.averageAuthorizedFees[tokenAddressLC] = {\n ...baseFee,\n feePerUnitGas: '0x' + averageFee.toString(16),\n };\n });\n }\n\n static getAuthorizedFee(tokenAddress: string): Optional<CachedTokenFee> {\n return this.averageAuthorizedFees[tokenAddress.toLowerCase()];\n }\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
|
|
2
|
+
import { BroadcasterFeeCache } from './broadcaster-fee-cache.js';
|
|
3
|
+
import { cachedFeeExpired } from '../utils/broadcaster-util.js';
|
|
4
|
+
export const handleAuthorizedFees = (feeMessageData, signerAddress) => {
|
|
5
|
+
try {
|
|
6
|
+
if (cachedFeeExpired(feeMessageData.feeExpiration)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const tokenFeeMap = {};
|
|
10
|
+
const tokenAddresses = Object.keys(feeMessageData.fees);
|
|
11
|
+
tokenAddresses.forEach(tokenAddress => {
|
|
12
|
+
const feePerUnitGas = feeMessageData.fees[tokenAddress];
|
|
13
|
+
if (feePerUnitGas) {
|
|
14
|
+
const cachedFee = {
|
|
15
|
+
feePerUnitGas,
|
|
16
|
+
expiration: feeMessageData.feeExpiration,
|
|
17
|
+
feesID: feeMessageData.feesID,
|
|
18
|
+
availableWallets: feeMessageData.availableWallets,
|
|
19
|
+
relayAdapt: feeMessageData.relayAdapt,
|
|
20
|
+
reliability: feeMessageData.reliability,
|
|
21
|
+
};
|
|
22
|
+
tokenFeeMap[tokenAddress] = cachedFee;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
if (Object.keys(tokenFeeMap).length > 0) {
|
|
26
|
+
BroadcasterFeeCache.addAuthorizedFees(signerAddress, tokenFeeMap);
|
|
27
|
+
BroadcasterDebug.log('Updated Authorized Fees');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
BroadcasterDebug.error(err);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=handle-authorized-fees-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-authorized-fees-message.js","sourceRoot":"","sources":["../../src/fees/handle-authorized-fees-message.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,cAAyC,EACzC,aAAqB,EACrB,EAAE;IACF,IAAI,CAAC;QACH,IAAI,gBAAgB,CAAC,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAA4B,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACxD,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YACpC,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACxD,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,SAAS,GAAmB;oBAChC,aAAa;oBACb,UAAU,EAAE,cAAc,CAAC,aAAa;oBACxC,MAAM,EAAE,cAAc,CAAC,MAAM;oBAC7B,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;oBACjD,UAAU,EAAE,cAAc,CAAC,UAAU;oBACrC,WAAW,EAAE,cAAc,CAAC,WAAW;iBACxC,CAAC;gBACF,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;YACxC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,mBAAmB,CAAC,iBAAiB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;YAClE,gBAAgB,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gBAAgB,CAAC,KAAK,CAAC,GAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC,CAAC","sourcesContent":["import {\n BroadcasterFeeMessageData,\n CachedTokenFee,\n} from '@railgun-community/shared-models';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { BroadcasterFeeCache } from './broadcaster-fee-cache.js';\nimport { cachedFeeExpired } from '../utils/broadcaster-util.js';\n\nexport const handleAuthorizedFees = (\n feeMessageData: BroadcasterFeeMessageData,\n signerAddress: string,\n) => {\n try {\n if (cachedFeeExpired(feeMessageData.feeExpiration)) {\n return;\n }\n\n const tokenFeeMap: MapType<CachedTokenFee> = {};\n const tokenAddresses = Object.keys(feeMessageData.fees);\n tokenAddresses.forEach(tokenAddress => {\n const feePerUnitGas = feeMessageData.fees[tokenAddress];\n if (feePerUnitGas) {\n const cachedFee: CachedTokenFee = {\n feePerUnitGas,\n expiration: feeMessageData.feeExpiration,\n feesID: feeMessageData.feesID,\n availableWallets: feeMessageData.availableWallets,\n relayAdapt: feeMessageData.relayAdapt,\n reliability: feeMessageData.reliability,\n };\n tokenFeeMap[tokenAddress] = cachedFee;\n }\n });\n\n if (Object.keys(tokenFeeMap).length > 0) {\n BroadcasterFeeCache.addAuthorizedFees(signerAddress, tokenFeeMap);\n BroadcasterDebug.log('Updated Authorized Fees');\n }\n } catch (err) {\n BroadcasterDebug.error(err as Error);\n }\n};\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Chain } from '@railgun-community/shared-models';
|
|
2
|
-
import { IMessage } from '@waku/
|
|
2
|
+
import { type IMessage } from '@waku/sdk';
|
|
3
3
|
export declare const handleBroadcasterFeesMessage: (chain: Chain, message: IMessage, contentTopic: string) => Promise<void>;
|
|
@@ -7,6 +7,7 @@ import { BroadcasterFeeCache } from './broadcaster-fee-cache.js';
|
|
|
7
7
|
import { invalidBroadcasterVersion } from '../utils/broadcaster-util.js';
|
|
8
8
|
import { bytesToUtf8, hexToUTF8String } from '../utils/conversion.js';
|
|
9
9
|
import { isDefined } from '../utils/is-defined.js';
|
|
10
|
+
import { handleAuthorizedFees } from './handle-authorized-fees-message.js';
|
|
10
11
|
const isExpiredTimestamp = (timestamp, expirationFeeTimestamp) => {
|
|
11
12
|
if (!timestamp || !expirationFeeTimestamp) {
|
|
12
13
|
return false;
|
|
@@ -17,6 +18,7 @@ const isExpiredTimestamp = (timestamp, expirationFeeTimestamp) => {
|
|
|
17
18
|
}
|
|
18
19
|
const nowTime = Date.now();
|
|
19
20
|
const expirationMsec = nowTime - 45 * 1000;
|
|
21
|
+
const expirationFeeMsec = nowTime + 45 * 1000;
|
|
20
22
|
const timestampExpired = messageTimestamp.getTime() < expirationMsec;
|
|
21
23
|
if (timestampExpired) {
|
|
22
24
|
BroadcasterDebug.log(`Broadcaster Fee STALE: Difference was ${(Date.now() - messageTimestamp.getTime()) / 1000}s`);
|
|
@@ -24,7 +26,8 @@ const isExpiredTimestamp = (timestamp, expirationFeeTimestamp) => {
|
|
|
24
26
|
else {
|
|
25
27
|
BroadcasterDebug.log(`Broadcaster Fee receipt SUCCESS in ${(Date.now() - messageTimestamp.getTime()) / 1000}s`);
|
|
26
28
|
}
|
|
27
|
-
|
|
29
|
+
const feeExpired = expirationFeeTimestamp.getTime() < expirationFeeMsec;
|
|
30
|
+
return timestampExpired && feeExpired;
|
|
28
31
|
};
|
|
29
32
|
export const handleBroadcasterFeesMessage = async (chain, message, contentTopic) => {
|
|
30
33
|
try {
|
|
@@ -66,15 +69,49 @@ export const handleBroadcasterFeesMessage = async (chain, message, contentTopic)
|
|
|
66
69
|
if (!(cause instanceof Error)) {
|
|
67
70
|
throw new Error('Unexpected non-error thrown', { cause });
|
|
68
71
|
}
|
|
69
|
-
BroadcasterDebug.error(new Error('Error handling Broadcaster fees', { cause }));
|
|
70
72
|
}
|
|
71
73
|
};
|
|
72
74
|
const updateFeesForBroadcaster = (chain, feeMessageData) => {
|
|
73
75
|
const tokenFeeMap = {};
|
|
74
76
|
const tokenAddresses = Object.keys(feeMessageData.fees);
|
|
77
|
+
let isTrustedSigner = false;
|
|
78
|
+
if (BroadcasterConfig.trustedFeeSigner) {
|
|
79
|
+
if (typeof BroadcasterConfig.trustedFeeSigner === 'string') {
|
|
80
|
+
isTrustedSigner =
|
|
81
|
+
feeMessageData.railgunAddress.toLowerCase() ===
|
|
82
|
+
BroadcasterConfig.trustedFeeSigner.toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
isTrustedSigner = BroadcasterConfig.trustedFeeSigner.map(s => s.toLowerCase()).includes(feeMessageData.railgunAddress.toLowerCase());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (isTrustedSigner) {
|
|
89
|
+
handleAuthorizedFees(feeMessageData, feeMessageData.railgunAddress);
|
|
90
|
+
}
|
|
75
91
|
tokenAddresses.forEach(tokenAddress => {
|
|
76
92
|
const feePerUnitGas = feeMessageData.fees[tokenAddress];
|
|
77
93
|
if (feePerUnitGas) {
|
|
94
|
+
if (!isTrustedSigner && BroadcasterConfig.trustedFeeSigner) {
|
|
95
|
+
const authorizedFee = BroadcasterFeeCache.getAuthorizedFee(tokenAddress.toLowerCase());
|
|
96
|
+
if (authorizedFee) {
|
|
97
|
+
const authorizedFeeAmount = BigInt(authorizedFee.feePerUnitGas);
|
|
98
|
+
const varianceLower = (authorizedFeeAmount *
|
|
99
|
+
BigInt(Math.round(BroadcasterConfig.authorizedFeeVariancePercentageLower * 100))) /
|
|
100
|
+
100n;
|
|
101
|
+
const varianceUpper = (authorizedFeeAmount *
|
|
102
|
+
BigInt(Math.round(BroadcasterConfig.authorizedFeeVariancePercentageUpper * 100))) /
|
|
103
|
+
100n;
|
|
104
|
+
const minFee = authorizedFeeAmount - varianceLower;
|
|
105
|
+
const maxFee = authorizedFeeAmount + varianceUpper;
|
|
106
|
+
const feeAmount = BigInt(feePerUnitGas);
|
|
107
|
+
if (feeAmount < minFee || feeAmount > maxFee) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
78
115
|
const cachedFee = {
|
|
79
116
|
feePerUnitGas,
|
|
80
117
|
expiration: feeMessageData.feeExpiration,
|
|
@@ -86,6 +123,8 @@ const updateFeesForBroadcaster = (chain, feeMessageData) => {
|
|
|
86
123
|
tokenFeeMap[tokenAddress] = cachedFee;
|
|
87
124
|
}
|
|
88
125
|
});
|
|
89
|
-
|
|
126
|
+
if (Object.keys(tokenFeeMap).length > 0) {
|
|
127
|
+
BroadcasterFeeCache.addTokenFees(chain, feeMessageData.railgunAddress, feeMessageData.feeExpiration, tokenFeeMap, feeMessageData.identifier, feeMessageData.version, feeMessageData.requiredPOIListKeys ?? []);
|
|
128
|
+
}
|
|
90
129
|
};
|
|
91
130
|
//# sourceMappingURL=handle-fees-message.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-fees-message.js","sourceRoot":"","sources":["../../src/fees/handle-fees-message.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,2BAA2B,CAAC;AAMnC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,kBAAkB,GAAG,CACzB,SAAyB,EACzB,sBAAsC,EACtC,EAAE;IACF,IAAI,CAAC,SAAS,IAAI,CAAC,sBAAsB,EAAE;QACzC,OAAO,KAAK,CAAC;KACd;IACD,IAAI,gBAAgB,GAAG,SAAS,CAAC;IACjC,IAAI,gBAAgB,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QAE3C,gBAAgB,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;KAChE;IAGD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,cAAc,GAAG,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC;IAE3C,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,EAAE,GAAG,cAAc,CAAC;IACrE,IAAI,gBAAgB,EAAE;QACpB,gBAAgB,CAAC,GAAG,CAClB,yCACE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,IAC9C,GAAG,CACJ,CAAC;KACH;SAAM;QACL,gBAAgB,CAAC,GAAG,CAClB,sCACE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,IAC9C,GAAG,CACJ,CAAC;KACH;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,EAC/C,KAAY,EACZ,OAAiB,EACjB,YAAoB,EACpB,EAAE;IACF,IAAI;QACF,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;YAC/B,gBAAgB,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YACtE,OAAO;SACR;QACD,IAAI,YAAY,KAAK,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC9C,gBAAgB,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;YACvE,OAAO;SACR;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAG7C,CAAC;QACF,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAA8B,CAAC;QAC3E,MAAM,iBAAiB,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACjE,IAAI,kBAAkB,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE;YAC5D,gBAAgB,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YACjE,OAAO;SACR;QAED,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,MAAM,EAAE;YACzD,gBAAgB,CAAC,GAAG,CAClB,mHAAmH,CACpH,CAAC;YACF,wBAAwB,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;YAChD,OAAO;SACR;QAED,IAAI,yBAAyB,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;YACrD,gBAAgB,CAAC,GAAG,CAClB,+CAA+C,cAAc,CAAC,OAAO,KAAK,cAAc,CAAC,cAAc,EAAE,CAC1G,CAAC;YACF,OAAO;SACR;QAED,MAAM,EAAE,cAAc,EAAE,GAAG,cAAc,CAAC;QAC1C,MAAM,EAAE,gBAAgB,EAAE,GAAG,2BAA2B,CAAC,cAAc,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAC/C,SAAS,EACT,IAAI,EACJ,gBAAgB,CACjB,CAAC;QACF,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO;SACR;QAED,wBAAwB,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;KACjD;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;SAC3D;QAED,gBAAgB,CAAC,KAAK,CACpB,IAAI,KAAK,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,CAAC,CACxD,CAAC;KACH;AACH,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,CAC/B,KAAY,EACZ,cAAyC,EACzC,EAAE;IACF,MAAM,WAAW,GAA4B,EAAE,CAAC;IAChD,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACxD,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;QACpC,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,aAAa,EAAE;YACjB,MAAM,SAAS,GAAmB;gBAChC,aAAa;gBACb,UAAU,EAAE,cAAc,CAAC,aAAa;gBACxC,MAAM,EAAE,cAAc,CAAC,MAAM;gBAC7B,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;gBACjD,UAAU,EAAE,cAAc,CAAC,UAAU;gBACrC,WAAW,EAAE,cAAc,CAAC,WAAW;aACxC,CAAC;YACF,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;SACvC;IACH,CAAC,CAAC,CAAC;IAEH,mBAAmB,CAAC,YAAY,CAC9B,KAAK,EACL,cAAc,CAAC,cAAc,EAC7B,cAAc,CAAC,aAAa,EAC5B,WAAW,EACX,cAAc,CAAC,UAAU,EACzB,cAAc,CAAC,OAAO,EACtB,cAAc,CAAC,mBAAmB,IAAI,EAAE,CACzC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n verifyBroadcasterSignature,\n getRailgunWalletAddressData,\n} from '@railgun-community/wallet';\nimport {\n CachedTokenFee,\n Chain,\n BroadcasterFeeMessageData,\n} from '@railgun-community/shared-models';\nimport crypto from 'crypto';\nimport { IMessage } from '@waku/interfaces';\nimport { contentTopics } from '../waku/waku-topics.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { BroadcasterFeeCache } from './broadcaster-fee-cache.js';\nimport { invalidBroadcasterVersion } from '../utils/broadcaster-util.js';\nimport { bytesToUtf8, hexToUTF8String } from '../utils/conversion.js';\nimport { isDefined } from '../utils/is-defined.js';\n\nconst isExpiredTimestamp = (\n timestamp: Optional<Date>,\n expirationFeeTimestamp: Optional<Date>,\n) => {\n if (!timestamp || !expirationFeeTimestamp) {\n return false;\n }\n let messageTimestamp = timestamp;\n if (messageTimestamp.getFullYear() === 1970) {\n // Waku timestamp bug.\n messageTimestamp = new Date(messageTimestamp.getTime() * 1000);\n }\n // Expired if message originated > 45 seconds ago.\n // check if fee expires within 45 seconds; if it doesn't ignore it.\n const nowTime = Date.now();\n const expirationMsec = nowTime - 45 * 1000;\n // const expirationFeeMsec = nowTime + 45 * 1000;\n const timestampExpired = messageTimestamp.getTime() < expirationMsec;\n if (timestampExpired) {\n BroadcasterDebug.log(\n `Broadcaster Fee STALE: Difference was ${\n (Date.now() - messageTimestamp.getTime()) / 1000\n }s`,\n );\n } else {\n BroadcasterDebug.log(\n `Broadcaster Fee receipt SUCCESS in ${\n (Date.now() - messageTimestamp.getTime()) / 1000\n }s`,\n );\n }\n // const feeExpired = expirationFeeTimestamp.getTime() < expirationFeeMsec;\n return timestampExpired; // || feeExpired;\n};\n\nexport const handleBroadcasterFeesMessage = async (\n chain: Chain,\n message: IMessage,\n contentTopic: string,\n) => {\n try {\n if (!isDefined(message.payload)) {\n BroadcasterDebug.log('Skipping Broadcaster fees message: NO PAYLOAD');\n return;\n }\n if (contentTopic !== contentTopics.fees(chain)) {\n BroadcasterDebug.log('Skipping Broadcaster fees message: WRONG TOPIC');\n return;\n }\n const payload = bytesToUtf8(message.payload);\n const { data, signature } = JSON.parse(payload) as {\n data: string;\n signature: string;\n };\n const utf8String = hexToUTF8String(data);\n const feeMessageData = JSON.parse(utf8String) as BroadcasterFeeMessageData;\n const feeExpirationTime = new Date(feeMessageData.feeExpiration);\n if (isExpiredTimestamp(message.timestamp, feeExpirationTime)) {\n BroadcasterDebug.log('Skipping fee message. Timestamp Expired.');\n return;\n }\n\n if (!isDefined(crypto.subtle) && BroadcasterConfig.IS_DEV) {\n BroadcasterDebug.log(\n 'Skipping Broadcaster fee validation in DEV. `crypto.subtle` does not exist (not secure: use https or localhost). ',\n );\n updateFeesForBroadcaster(chain, feeMessageData);\n return;\n }\n\n if (invalidBroadcasterVersion(feeMessageData.version)) {\n BroadcasterDebug.log(\n `Skipping Broadcaster outside version range: ${feeMessageData.version}, ${feeMessageData.railgunAddress}`,\n );\n return;\n }\n\n const { railgunAddress } = feeMessageData;\n const { viewingPublicKey } = getRailgunWalletAddressData(railgunAddress);\n const verified = await verifyBroadcasterSignature(\n signature,\n data,\n viewingPublicKey,\n );\n if (!verified) {\n return;\n }\n\n updateFeesForBroadcaster(chain, feeMessageData);\n } catch (cause) {\n if (!(cause instanceof Error)) {\n throw new Error('Unexpected non-error thrown', { cause });\n }\n\n BroadcasterDebug.error(\n new Error('Error handling Broadcaster fees', { cause }),\n );\n }\n};\n\nconst updateFeesForBroadcaster = (\n chain: Chain,\n feeMessageData: BroadcasterFeeMessageData,\n) => {\n const tokenFeeMap: MapType<CachedTokenFee> = {};\n const tokenAddresses = Object.keys(feeMessageData.fees);\n tokenAddresses.forEach(tokenAddress => {\n const feePerUnitGas = feeMessageData.fees[tokenAddress];\n if (feePerUnitGas) {\n const cachedFee: CachedTokenFee = {\n feePerUnitGas,\n expiration: feeMessageData.feeExpiration,\n feesID: feeMessageData.feesID,\n availableWallets: feeMessageData.availableWallets,\n relayAdapt: feeMessageData.relayAdapt,\n reliability: feeMessageData.reliability,\n };\n tokenFeeMap[tokenAddress] = cachedFee;\n }\n });\n\n BroadcasterFeeCache.addTokenFees(\n chain,\n feeMessageData.railgunAddress,\n feeMessageData.feeExpiration,\n tokenFeeMap,\n feeMessageData.identifier,\n feeMessageData.version,\n feeMessageData.requiredPOIListKeys ?? [],\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"handle-fees-message.js","sourceRoot":"","sources":["../../src/fees/handle-fees-message.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n verifyBroadcasterSignature,\n getRailgunWalletAddressData,\n} from '@railgun-community/wallet';\nimport {\n CachedTokenFee,\n Chain,\n BroadcasterFeeMessageData,\n} from '@railgun-community/shared-models';\nimport crypto from 'crypto';\nimport { type IMessage } from '@waku/sdk';\nimport { contentTopics } from '../waku/waku-topics.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { BroadcasterConfig } from '../models/broadcaster-config.js';\nimport { BroadcasterFeeCache } from './broadcaster-fee-cache.js';\nimport { invalidBroadcasterVersion } from '../utils/broadcaster-util.js';\nimport { bytesToUtf8, hexToUTF8String } from '../utils/conversion.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport { handleAuthorizedFees } from './handle-authorized-fees-message.js';\n\nconst isExpiredTimestamp = (\n timestamp: Optional<Date>,\n expirationFeeTimestamp: Optional<Date>,\n) => {\n if (!timestamp || !expirationFeeTimestamp) {\n return false;\n }\n let messageTimestamp = timestamp;\n if (messageTimestamp.getFullYear() === 1970) {\n // Waku timestamp bug. -- should be no longer an issue. \n messageTimestamp = new Date(messageTimestamp.getTime() * 1000);\n }\n // Expired if message originated > 45 seconds ago.\n // check if fee expires within 45 seconds; if it doesn't ignore it.\n const nowTime = Date.now();\n const expirationMsec = nowTime - 45 * 1000;\n const expirationFeeMsec = nowTime + 45 * 1000;\n const timestampExpired = messageTimestamp.getTime() < expirationMsec;\n if (timestampExpired) {\n BroadcasterDebug.log(\n `Broadcaster Fee STALE: Difference was ${(Date.now() - messageTimestamp.getTime()) / 1000\n }s`,\n );\n } else {\n BroadcasterDebug.log(\n `Broadcaster Fee receipt SUCCESS in ${(Date.now() - messageTimestamp.getTime()) / 1000\n }s`,\n );\n }\n const feeExpired = expirationFeeTimestamp.getTime() < expirationFeeMsec;\n return timestampExpired && feeExpired;\n};\n\nexport const handleBroadcasterFeesMessage = async (\n chain: Chain,\n message: IMessage,\n contentTopic: string,\n) => {\n try {\n if (!isDefined(message.payload)) {\n BroadcasterDebug.log('Skipping Broadcaster fees message: NO PAYLOAD');\n return;\n }\n if (contentTopic !== contentTopics.fees(chain)) {\n BroadcasterDebug.log('Skipping Broadcaster fees message: WRONG TOPIC');\n return;\n }\n const payload = bytesToUtf8(message.payload);\n const { data, signature } = JSON.parse(payload) as {\n data: string;\n signature: string;\n };\n const utf8String = hexToUTF8String(data);\n const feeMessageData = JSON.parse(utf8String) as BroadcasterFeeMessageData;\n const feeExpirationTime = new Date(feeMessageData.feeExpiration);\n if (isExpiredTimestamp(message.timestamp, feeExpirationTime)) {\n BroadcasterDebug.log('Skipping fee message. Timestamp Expired.');\n return;\n }\n\n if (!isDefined(crypto.subtle) && BroadcasterConfig.IS_DEV) {\n BroadcasterDebug.log(\n 'Skipping Broadcaster fee validation in DEV. `crypto.subtle` does not exist (not secure: use https or localhost). ',\n );\n updateFeesForBroadcaster(chain, feeMessageData);\n return;\n }\n\n if (invalidBroadcasterVersion(feeMessageData.version)) {\n BroadcasterDebug.log(\n `Skipping Broadcaster outside version range: ${feeMessageData.version}, ${feeMessageData.railgunAddress}`,\n );\n return;\n }\n\n const { railgunAddress } = feeMessageData;\n const { viewingPublicKey } = getRailgunWalletAddressData(railgunAddress);\n const verified = await verifyBroadcasterSignature(\n signature,\n data,\n viewingPublicKey,\n );\n if (!verified) {\n return;\n }\n\n updateFeesForBroadcaster(chain, feeMessageData);\n } catch (cause) {\n if (!(cause instanceof Error)) {\n throw new Error('Unexpected non-error thrown', { cause });\n }\n }\n};\n\nconst updateFeesForBroadcaster = (\n chain: Chain,\n feeMessageData: BroadcasterFeeMessageData,\n) => {\n const tokenFeeMap: MapType<CachedTokenFee> = {};\n const tokenAddresses = Object.keys(feeMessageData.fees);\n\n let isTrustedSigner = false;\n if (BroadcasterConfig.trustedFeeSigner) {\n if (typeof BroadcasterConfig.trustedFeeSigner === 'string') {\n isTrustedSigner =\n feeMessageData.railgunAddress.toLowerCase() ===\n BroadcasterConfig.trustedFeeSigner.toLowerCase();\n } else {\n isTrustedSigner = BroadcasterConfig.trustedFeeSigner.map(s =>\n s.toLowerCase(),\n ).includes(feeMessageData.railgunAddress.toLowerCase());\n }\n }\n\n if (isTrustedSigner) {\n handleAuthorizedFees(feeMessageData, feeMessageData.railgunAddress);\n }\n\n tokenAddresses.forEach(tokenAddress => {\n const feePerUnitGas = feeMessageData.fees[tokenAddress];\n if (feePerUnitGas) {\n if (!isTrustedSigner && BroadcasterConfig.trustedFeeSigner) {\n const authorizedFee = BroadcasterFeeCache.getAuthorizedFee(\n tokenAddress.toLowerCase(),\n );\n if (authorizedFee) {\n const authorizedFeeAmount = BigInt(authorizedFee.feePerUnitGas);\n const varianceLower =\n (authorizedFeeAmount *\n BigInt(\n Math.round(\n BroadcasterConfig.authorizedFeeVariancePercentageLower * 100,\n ),\n )) /\n 100n;\n const varianceUpper =\n (authorizedFeeAmount *\n BigInt(\n Math.round(\n BroadcasterConfig.authorizedFeeVariancePercentageUpper * 100,\n ),\n )) /\n 100n;\n const minFee = authorizedFeeAmount - varianceLower;\n const maxFee = authorizedFeeAmount + varianceUpper;\n\n const feeAmount = BigInt(feePerUnitGas);\n if (feeAmount < minFee || feeAmount > maxFee) {\n return;\n }\n } else {\n // No authorized fee, and we require one.\n return;\n }\n }\n\n const cachedFee: CachedTokenFee = {\n feePerUnitGas,\n expiration: feeMessageData.feeExpiration,\n feesID: feeMessageData.feesID,\n availableWallets: feeMessageData.availableWallets,\n relayAdapt: feeMessageData.relayAdapt,\n reliability: feeMessageData.reliability,\n };\n tokenFeeMap[tokenAddress] = cachedFee;\n }\n });\n\n if (Object.keys(tokenFeeMap).length > 0) {\n BroadcasterFeeCache.addTokenFees(\n chain,\n feeMessageData.railgunAddress,\n feeMessageData.feeExpiration,\n tokenFeeMap,\n feeMessageData.identifier,\n feeMessageData.version,\n feeMessageData.requiredPOIListKeys ?? [],\n );\n }\n};\n"]}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
export type CustomDNSConfig = {
|
|
2
|
+
onlyCustom: boolean;
|
|
3
|
+
enrTreePeers: string[];
|
|
4
|
+
};
|
|
1
5
|
export declare class BroadcasterConfig {
|
|
2
6
|
static IS_DEV: boolean;
|
|
3
|
-
static
|
|
4
|
-
static
|
|
7
|
+
static trustedFeeSigner: string | string[];
|
|
8
|
+
static feeExpirationTimeout: number;
|
|
9
|
+
static historicalLookBackTime: number;
|
|
10
|
+
static authorizedFeeVariancePercentageLower: number;
|
|
11
|
+
static authorizedFeeVariancePercentageUpper: number;
|
|
12
|
+
static MINIMUM_BROADCASTER_VERSION: string;
|
|
13
|
+
static MAXIMUM_BROADCASTER_VERSION: string;
|
|
14
|
+
static useDNSDiscovery: boolean;
|
|
15
|
+
static customDNS: CustomDNSConfig | undefined;
|
|
5
16
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
export class BroadcasterConfig {
|
|
2
2
|
static IS_DEV = false;
|
|
3
|
+
static trustedFeeSigner;
|
|
4
|
+
static feeExpirationTimeout = 120_000;
|
|
5
|
+
static historicalLookBackTime = 1 * 60 * 1000;
|
|
6
|
+
static authorizedFeeVariancePercentageLower = 0.10;
|
|
7
|
+
static authorizedFeeVariancePercentageUpper = 0.30;
|
|
3
8
|
static MINIMUM_BROADCASTER_VERSION = '8.0.0';
|
|
4
9
|
static MAXIMUM_BROADCASTER_VERSION = '8.999.0';
|
|
10
|
+
static useDNSDiscovery = false;
|
|
11
|
+
static customDNS = undefined;
|
|
5
12
|
}
|
|
6
13
|
//# sourceMappingURL=broadcaster-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcaster-config.js","sourceRoot":"","sources":["../../src/models/broadcaster-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"broadcaster-config.js","sourceRoot":"","sources":["../../src/models/broadcaster-config.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;IAEtB,MAAM,CAAC,gBAAgB,CAAoB;IAE3C,MAAM,CAAC,oBAAoB,GAAG,OAAO,CAAC;IACtC,MAAM,CAAC,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAE9C,MAAM,CAAC,oCAAoC,GAAG,IAAI,CAAC;IACnD,MAAM,CAAC,oCAAoC,GAAG,IAAI,CAAC;IAEnD,MAAM,CAAC,2BAA2B,GAAG,OAAO,CAAC;IAC7C,MAAM,CAAC,2BAA2B,GAAG,SAAS,CAAC;IAE/C,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,MAAM,CAAC,SAAS,GAAgC,SAAS,CAAA","sourcesContent":["export type CustomDNSConfig = {\n onlyCustom: boolean,\n enrTreePeers: string[]\n}\nexport class BroadcasterConfig {\n static IS_DEV = false;\n\n static trustedFeeSigner: string | string[];\n\n static feeExpirationTimeout = 120_000; // 2 minutes\n static historicalLookBackTime = 1 * 60 * 1000; // 1 minute\n\n static authorizedFeeVariancePercentageLower = 0.10; // 10% lower variance\n static authorizedFeeVariancePercentageUpper = 0.30; // 30% upper variance\n\n static MINIMUM_BROADCASTER_VERSION = '8.0.0';\n static MAXIMUM_BROADCASTER_VERSION = '8.999.0';\n\n static useDNSDiscovery = false\n static customDNS: CustomDNSConfig | undefined = undefined\n}\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export declare const WAKU_RAILGUN_PUB_SUB_TOPIC = "/waku/2/rs/
|
|
1
|
+
export declare const WAKU_RAILGUN_PUB_SUB_TOPIC = "/waku/2/rs/1/1";
|
|
2
2
|
export declare const WAKU_RAILGUN_DEFAULT_SHARD: {
|
|
3
3
|
clusterId: number;
|
|
4
4
|
shard: number;
|
|
5
|
+
shardId: number;
|
|
6
|
+
pubsubTopic: string;
|
|
5
7
|
};
|
|
6
8
|
export declare const WAKU_RAILGUN_DEFAULT_SHARDS: {
|
|
7
9
|
clusterId: number;
|
package/dist/models/constants.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
export const WAKU_RAILGUN_PUB_SUB_TOPIC = '/waku/2/rs/
|
|
1
|
+
export const WAKU_RAILGUN_PUB_SUB_TOPIC = '/waku/2/rs/1/1';
|
|
2
2
|
export const WAKU_RAILGUN_DEFAULT_SHARD = {
|
|
3
|
-
clusterId:
|
|
3
|
+
clusterId: 1,
|
|
4
4
|
shard: 1,
|
|
5
|
+
shardId: 1,
|
|
6
|
+
pubsubTopic: WAKU_RAILGUN_PUB_SUB_TOPIC,
|
|
5
7
|
};
|
|
6
8
|
export const WAKU_RAILGUN_DEFAULT_SHARDS = {
|
|
7
|
-
clusterId:
|
|
9
|
+
clusterId: 1,
|
|
8
10
|
shards: [0, 1, 2, 3, 4, 5],
|
|
9
11
|
};
|
|
10
|
-
export const WAKU_RAILGUN_DEFAULT_PEERS_WEB = [
|
|
11
|
-
|
|
12
|
-
'/dns4/fleet.rootedinprivacy.com/tcp/8000/wss/p2p/16Uiu2HAm3GnUDQhBfax298CMkZX9MBHTJ9B8GXhrbueozESUaRZP',
|
|
13
|
-
];
|
|
14
|
-
export const WAKU_RAILGUN_DEFAULT_PEERS_NODE = [
|
|
15
|
-
'/dns4/core.rootedinprivacy.com/tcp/60000/p2p/16Uiu2HAm4Ai1GzKv4EykU26ST1BPT4AHtABsYCLKrDG74GWX7D6H',
|
|
16
|
-
'/dns4/fleet.rootedinprivacy.com/tcp/60000/p2p/16Uiu2HAm3GnUDQhBfax298CMkZX9MBHTJ9B8GXhrbueozESUaRZP',
|
|
17
|
-
];
|
|
12
|
+
export const WAKU_RAILGUN_DEFAULT_PEERS_WEB = [];
|
|
13
|
+
export const WAKU_RAILGUN_DEFAULT_PEERS_NODE = [];
|
|
18
14
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/models/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CAAC;AAE3D,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,SAAS,EAAE,CAAC;IACZ,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/models/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CAAC;AAE3D,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,SAAS,EAAE,CAAC;IACZ,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,0BAA0B;CACxC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,SAAS,EAAE,CAAC;IACZ,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAa,EAEvD,CAAC;AAEF,MAAM,CAAC,MAAM,+BAA+B,GAAa,EAExD,CAAC","sourcesContent":["export const WAKU_RAILGUN_PUB_SUB_TOPIC = '/waku/2/rs/1/1';\n\nexport const WAKU_RAILGUN_DEFAULT_SHARD = {\n clusterId: 1,\n shard: 1,\n shardId: 1,\n pubsubTopic: WAKU_RAILGUN_PUB_SUB_TOPIC,\n};\n\nexport const WAKU_RAILGUN_DEFAULT_SHARDS = {\n clusterId: 1,\n shards: [0, 1, 2, 3, 4, 5],\n};\n\nexport const WAKU_RAILGUN_DEFAULT_PEERS_WEB: string[] = [\n // Some Websocket broadcasters (web friendly):\n];\n\nexport const WAKU_RAILGUN_DEFAULT_PEERS_NODE: string[] = [\n // Some TCP broadcasters (node friendly):\n];\n"]}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { Chain, BroadcasterConnectionStatus } from '@railgun-community/shared-models';
|
|
2
|
+
import type { CustomDNSConfig } from './broadcaster-config.js';
|
|
2
3
|
export type BroadcasterOptions = {
|
|
4
|
+
trustedFeeSigner: string | string[];
|
|
3
5
|
poiActiveListKeys?: string[];
|
|
4
6
|
pubSubTopic?: string;
|
|
5
7
|
additionalDirectPeers?: string[];
|
|
6
8
|
peerDiscoveryTimeout?: number;
|
|
9
|
+
feeExpirationTimeout?: number;
|
|
10
|
+
historicalLookBackTime?: number;
|
|
11
|
+
useDNSDiscovery?: boolean;
|
|
12
|
+
useCustomDNS?: CustomDNSConfig;
|
|
13
|
+
broadcasterVersionRange?: {
|
|
14
|
+
minVersion: string;
|
|
15
|
+
maxVersion: string;
|
|
16
|
+
};
|
|
7
17
|
};
|
|
8
18
|
export type BroadcasterConnectionStatusCallback = (chain: Chain, status: BroadcasterConnectionStatus) => void;
|
|
9
19
|
export type BroadcasterDebugger = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-models.js","sourceRoot":"","sources":["../../src/models/export-models.ts"],"names":[],"mappings":"","sourcesContent":["import {\n Chain,\n BroadcasterConnectionStatus,\n} from '@railgun-community/shared-models';\n\nexport type BroadcasterOptions = {\n poiActiveListKeys?: string[];\n pubSubTopic?: string;\n additionalDirectPeers?: string[];\n peerDiscoveryTimeout?: number;\n};\n\nexport type BroadcasterConnectionStatusCallback = (\n chain: Chain,\n status: BroadcasterConnectionStatus,\n) => void;\n\nexport type BroadcasterDebugger = {\n log: (msg: string) => void;\n error: (error: Error) => void;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"export-models.js","sourceRoot":"","sources":["../../src/models/export-models.ts"],"names":[],"mappings":"","sourcesContent":["import {\n Chain,\n BroadcasterConnectionStatus,\n} from '@railgun-community/shared-models';\nimport type { CustomDNSConfig } from './broadcaster-config.js';\n\nexport type BroadcasterOptions = {\n trustedFeeSigner: string | string[];\n poiActiveListKeys?: string[];\n pubSubTopic?: string;\n additionalDirectPeers?: string[];\n peerDiscoveryTimeout?: number;\n feeExpirationTimeout?: number;\n historicalLookBackTime?: number;\n useDNSDiscovery?: boolean;\n useCustomDNS?: CustomDNSConfig,\n broadcasterVersionRange?: {\n minVersion: string;\n maxVersion: string;\n };\n};\n\nexport type BroadcasterConnectionStatusCallback = (\n chain: Chain,\n status: BroadcasterConnectionStatus,\n) => void;\n\nexport type BroadcasterDebugger = {\n log: (msg: string) => void;\n error: (error: Error) => void;\n};\n"]}
|