@superfluid-finance/ethereum-contracts 1.3.2-dev.bf84335.0 → 1.3.2-dev.ccb1898.0

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 (122) hide show
  1. package/build/contracts/AccessControl.json +1 -1
  2. package/build/contracts/AccessControlEnumerable.json +1 -1
  3. package/build/contracts/Address.json +1 -1
  4. package/build/contracts/AgreementBase.json +18 -18
  5. package/build/contracts/AgreementLibrary.json +1272 -1183
  6. package/build/contracts/BaseRelayRecipient.json +55 -55
  7. package/build/contracts/BatchLiquidator.json +211 -211
  8. package/build/contracts/BatchOperation.json +599 -599
  9. package/build/contracts/CFAv1Library.json +2282 -2282
  10. package/build/contracts/CallUtils.json +198 -198
  11. package/build/contracts/ClosingOnUpdateFlowTestApp.json +2472 -2472
  12. package/build/contracts/ConstantFlowAgreementV1.json +12931 -13308
  13. package/build/contracts/Context.json +1 -1
  14. package/build/contracts/ContextDefinitions.json +599 -599
  15. package/build/contracts/Create2.json +1 -1
  16. package/build/contracts/CustomSuperTokenBase.json +20 -20
  17. package/build/contracts/ERC165.json +1 -1
  18. package/build/contracts/ERC1820Implementer.json +1 -1
  19. package/build/contracts/ERC1820RegistryCompiled.json +22 -22
  20. package/build/contracts/ERC20.json +1 -1
  21. package/build/contracts/ERC20Burnable.json +1 -1
  22. package/build/contracts/ERC20Pausable.json +1 -1
  23. package/build/contracts/ERC20PresetMinterPauser.json +1 -1
  24. package/build/contracts/ERC20WithTokenInfo.json +23 -23
  25. package/build/contracts/ERC777Helper.json +380 -380
  26. package/build/contracts/ERC777RecipientDrainingGas.json +858 -858
  27. package/build/contracts/ERC777RecipientReverting.json +858 -858
  28. package/build/contracts/EnumerableSet.json +1 -1
  29. package/build/contracts/EventsEmitter.json +43 -43
  30. package/build/contracts/ExclusiveInflowTestApp.json +2473 -2473
  31. package/build/contracts/FixedSizeData.json +200 -200
  32. package/build/contracts/FlowExchangeTestApp.json +2473 -2473
  33. package/build/contracts/FlowOperatorDefinitions.json +599 -599
  34. package/build/contracts/FullUpgradableSuperTokenProxy.json +115 -115
  35. package/build/contracts/IAccessControl.json +1 -1
  36. package/build/contracts/IAccessControlEnumerable.json +1 -1
  37. package/build/contracts/IConstantFlowAgreementV1.json +567 -567
  38. package/build/contracts/IDAv1Library.json +2614 -2614
  39. package/build/contracts/IERC165.json +1 -1
  40. package/build/contracts/IERC1820Implementer.json +1 -1
  41. package/build/contracts/IERC1820Registry.json +1 -1
  42. package/build/contracts/IERC20.json +1 -1
  43. package/build/contracts/IERC20Metadata.json +1 -1
  44. package/build/contracts/IERC20Permit.json +1 -1
  45. package/build/contracts/IERC777.json +1 -1
  46. package/build/contracts/IERC777Recipient.json +1 -1
  47. package/build/contracts/IERC777Sender.json +1 -1
  48. package/build/contracts/IInstantDistributionAgreementV1.json +640 -640
  49. package/build/contracts/IMaticBridgedNativeSuperToken.json +63 -63
  50. package/build/contracts/IMaticBridgedNativeSuperTokenCustom.json +63 -63
  51. package/build/contracts/IMultiSigWallet.json +24 -24
  52. package/build/contracts/IPureSuperToken.json +43 -43
  53. package/build/contracts/IPureSuperTokenCustom.json +43 -43
  54. package/build/contracts/IRelayRecipient.json +27 -27
  55. package/build/contracts/IResolver.json +38 -38
  56. package/build/contracts/ISETH.json +48 -48
  57. package/build/contracts/ISETHCustom.json +48 -48
  58. package/build/contracts/ISuperAgreement.json +50 -50
  59. package/build/contracts/ISuperApp.json +192 -192
  60. package/build/contracts/ISuperToken.json +524 -524
  61. package/build/contracts/ISuperTokenFactory.json +161 -161
  62. package/build/contracts/ISuperfluid.json +1145 -1178
  63. package/build/contracts/ISuperfluidGovernance.json +243 -243
  64. package/build/contracts/ISuperfluidToken.json +389 -389
  65. package/build/contracts/ITOGAv1.json +1442 -1442
  66. package/build/contracts/ITOGAv2.json +1442 -1442
  67. package/build/contracts/Initializable.json +1 -1
  68. package/build/contracts/InstantDistributionAgreementV1.json +5820 -5820
  69. package/build/contracts/MaticBridgedNativeSuperTokenProxy.json +231 -231
  70. package/build/contracts/NonClosableOutflowTestApp.json +2473 -2473
  71. package/build/contracts/Ownable.json +1 -1
  72. package/build/contracts/Pausable.json +1 -1
  73. package/build/contracts/Proxy.json +1 -1
  74. package/build/contracts/PureSuperToken.json +109 -109
  75. package/build/contracts/Resolver.json +98 -98
  76. package/build/contracts/SETHProxy.json +227 -227
  77. package/build/contracts/SafeCast.json +1 -1
  78. package/build/contracts/SafeERC20.json +1 -1
  79. package/build/contracts/SafeMath.json +1 -1
  80. package/build/contracts/SelfDeletingFlowTestApp.json +2472 -2472
  81. package/build/contracts/SlotsBitmapLibrary.json +457 -457
  82. package/build/contracts/StreamRedirector.json +748 -748
  83. package/build/contracts/Strings.json +1 -1
  84. package/build/contracts/SuperAppBase.json +240 -240
  85. package/build/contracts/SuperAppDefinitions.json +599 -599
  86. package/build/contracts/SuperToken.json +4732 -4732
  87. package/build/contracts/SuperTokenFactory.json +750 -750
  88. package/build/contracts/SuperTokenFactoryBase.json +738 -738
  89. package/build/contracts/SuperTokenFactoryHelper.json +743 -743
  90. package/build/contracts/SuperUpgrader.json +440 -440
  91. package/build/contracts/Superfluid.json +15366 -16050
  92. package/build/contracts/SuperfluidFrameworkDeployer.json +765 -765
  93. package/build/contracts/SuperfluidGovernanceBase.json +2233 -2233
  94. package/build/contracts/SuperfluidGovernanceConfigs.json +599 -599
  95. package/build/contracts/SuperfluidGovernanceII.json +149 -149
  96. package/build/contracts/SuperfluidGovernanceIIProxy.json +131 -131
  97. package/build/contracts/SuperfluidLoader.json +210 -210
  98. package/build/contracts/SuperfluidToken.json +2420 -2420
  99. package/build/contracts/TOGA.json +1461 -1461
  100. package/build/contracts/TestGovernance.json +248 -248
  101. package/build/contracts/TestToken.json +93 -93
  102. package/build/contracts/TokenCustodian.json +214 -214
  103. package/build/contracts/TokenInfo.json +32 -32
  104. package/build/contracts/UUPSProxiable.json +139 -139
  105. package/build/contracts/UUPSProxy.json +81 -81
  106. package/build/contracts/UUPSUtils.json +37 -37
  107. package/build/contracts-sizes.txt +6 -6
  108. package/contracts/agreements/AgreementLibrary.sol +39 -15
  109. package/contracts/agreements/ConstantFlowAgreementV1.sol +65 -53
  110. package/contracts/interfaces/superfluid/ISuperfluid.sol +29 -23
  111. package/contracts/mocks/AgreementMock.sol +2 -2
  112. package/contracts/mocks/CFAAppMocks.sol +1 -1
  113. package/contracts/mocks/MultiFlowTesterApp.sol +13 -12
  114. package/contracts/mocks/SuperTokenMock.sol +2 -2
  115. package/contracts/mocks/SuperfluidMock.sol +9 -9
  116. package/contracts/superfluid/Superfluid.sol +34 -38
  117. package/contracts/superfluid/SuperfluidToken.sol +14 -14
  118. package/package.json +2 -2
  119. package/scripts/deploy-mfa.ts +27 -0
  120. package/scripts/libs/getConfig.js +14 -0
  121. package/utils/README.md +18 -0
  122. package/utils/mfa-tester.html +687 -0
@@ -0,0 +1,687 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <title>Multi Flow Block Explorer</title>
6
+ <meta charset="utf-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css"
9
+ integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
10
+ <script src="https://cdn.jsdelivr.net/npm/ethers@5.6.0/dist/ethers.umd.min.js"
11
+ integrity="sha256-I/T7C/qM1p/EIawMnVp+b68aGIgHpiaW5uJm8Xd/WYg=" crossorigin="anonymous"></script>
12
+
13
+ <link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet">
14
+ <!-- minify -->
15
+ <link href="https://unpkg.com/nes.css@2.3.0/css/nes.min.css" rel="stylesheet" />
16
+
17
+ <!-- sdk-core -->
18
+ <script src="./dist/index.umd.js"></script>
19
+ <!-- vue.js -->
20
+ <script type="importmap">
21
+ {
22
+ "imports": {
23
+ "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
24
+ }
25
+ }
26
+ </script>
27
+ <style>
28
+ html, body, input, select {
29
+ color: #10BB35;
30
+ background: #151619 !important;
31
+ outline: none;
32
+ }
33
+ label {
34
+ display: table-cell;
35
+ }
36
+
37
+ input {
38
+ display: table-cell;
39
+ }
40
+ input, select {
41
+ border: 1px solid #10BB35;
42
+ }
43
+ p {
44
+ margin-bottom: 0;
45
+ color: #10BB35;
46
+ }
47
+
48
+ .input-table {
49
+ display: table;
50
+ }
51
+
52
+ .input-container {
53
+ display: table-row;
54
+ }
55
+
56
+ .receiver-container {
57
+ margin-bottom: 1rem;
58
+ }
59
+
60
+ .loading {
61
+ width: 100vw;
62
+ height: 100vh;
63
+ z-index: 2;
64
+ position: absolute;
65
+ background-color: black;
66
+ opacity: 0.3;
67
+ top: 0;
68
+ left: 0;
69
+ color: white;
70
+ }
71
+ </style>
72
+
73
+ </head>
74
+
75
+ <body>
76
+ <script type="module">
77
+ import { computed, createApp, reactive, ref, onMounted, watch } from 'vue';
78
+
79
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
80
+ const RESOLVER_ADDRESS = "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512";
81
+ const MFA_ADDRESS = "0x9E545E3C0baAB3E08CdfD552C960A1050f373042";
82
+ const EMPTY_RECEIVER = { address: ZERO_ADDRESS, proportion: "0" };
83
+ const RESET_SNAPSHOT_ID = "RESET_SNAPSHOT";
84
+
85
+ createApp({
86
+ setup() {
87
+ let framework;
88
+ let token;
89
+ let passedSigner;
90
+ const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545/");
91
+ const abiCoder = new ethers.utils.AbiCoder();
92
+
93
+ // computed properties
94
+ const mfaData = reactive({ ratioPct: "", flowRate: "", mfaAddress: MFA_ADDRESS, signerAddress: "" });
95
+ const receivers = reactive([]); // Array<{ address: string, proportion: string }>
96
+ const accounts = reactive([]); // Array<string>
97
+ const tokenData = reactive({
98
+ address: "",
99
+ balance: 0,
100
+ name: "",
101
+ underlyingAddress: "",
102
+ underlyingBalance: 0,
103
+ underlyingName: "",
104
+ });
105
+ const balanceData = reactive({
106
+ sender: {},
107
+ mfa: {},
108
+ receivers: []
109
+ });
110
+ const agreementData = reactive({
111
+ senderToMfa: {},
112
+ mfaToReceivers: []
113
+ });
114
+ const flowData = reactive({
115
+ flowRate: "",
116
+ sender: "",
117
+ receiver: ""
118
+ })
119
+
120
+ const receiverAddresses = computed(() => receivers.map(x => x.address));
121
+ const filteredReceivers = computed(() => receivers.filter(x => x.proportion > 0));
122
+ const signerAddress = computed(() => signer && signer.value ? signer.value._address : "n/a");
123
+ const providerNetwork = computed(() => provider && provider ? provider._network : "n/a");
124
+
125
+ // reactive refs
126
+ const selected = ref("");
127
+ const currentToken = ref("ETHx");
128
+ const currentReceiverAddress = ref("");
129
+ const currentReceiverProportion = ref("");
130
+ const impersonatedSignerAddress = ref("");
131
+ const increaseTimeSeconds = ref("");
132
+ const signer = ref(null);
133
+ const loading = ref(true);
134
+ const balanceSum = ref("");
135
+ const blockTimestamp = ref("");
136
+
137
+ // watchers
138
+ watch(selected, (receiverAddress) => {
139
+ const receiver = receivers.find(x => x.address === receiverAddress);
140
+ if (receiver) {
141
+ currentReceiverProportion.value = receiver.proportion;
142
+ currentReceiverAddress.value = receiverAddress;
143
+ }
144
+ });
145
+ watch(signer, async (signer) => {
146
+ if (token) {
147
+ const { superTokenBalanceData, underlyingBalance } = await getBalanceData(signer._address);
148
+ tokenData.balance = superTokenBalanceData.availableBalance;
149
+ tokenData.underlyingBalance = toBN(underlyingBalance);
150
+ }
151
+ });
152
+ watch(accounts, async (accounts) => {
153
+ try {
154
+ if (accounts.length > 0) {
155
+ await initialize();
156
+ const { superTokenBalanceData } = await getBalanceData(signer.value._address);
157
+ const signers = await getSigners();
158
+ if (Number(superTokenBalanceData.availableBalance) === 0) {
159
+ const upgradePromise = signers.map(x => upgradeToSuperToken(x));
160
+ await Promise.all(upgradePromise);
161
+ }
162
+ await loadToken();
163
+ await getAndSetSumBalance(signers.map(x => x._address));
164
+ }
165
+ if (!sessionStorage.getItem(RESET_SNAPSHOT_ID)) {
166
+ const snapshotId = await takeSnapshotAndReturnId();
167
+ sessionStorage.setItem(RESET_SNAPSHOT_ID, snapshotId);
168
+ }
169
+ } catch (err) {
170
+ console.error(err);
171
+ } finally {
172
+ loading.value = false;
173
+ }
174
+ });
175
+
176
+ const hasValidMFAInput = () => {
177
+ return mfaData.ratioPct !== ""
178
+ && mfaData.flowRate !== ""
179
+ && isAddress(mfaData.signerAddress)
180
+ && filteredReceivers.value.length > 0;
181
+ }
182
+ const isAddress = (address) => {
183
+ return ethers.utils.isAddress(address);
184
+ }
185
+
186
+ // receivers crud
187
+ const addReceiver = () => {
188
+ let newAddress;
189
+ if (currentReceiverAddress.value !== "" || currentReceiverProportion.value !== "") {
190
+
191
+ const currentData = {
192
+ address: currentReceiverAddress.value,
193
+ proportion: currentReceiverProportion.value
194
+ };
195
+ receivers.push(currentData);
196
+ newAddress = currentReceiverAddress.value;
197
+ } else {
198
+ receivers.push(EMPTY_RECEIVER);
199
+ newAddress = EMPTY_RECEIVER.address;
200
+ }
201
+ selected.value = newAddress;
202
+ };
203
+ const updateReceiver = () => {
204
+ const i = receivers.map(x => x.address).indexOf(selected.value);
205
+ receivers[i].address = selected.value = currentReceiverAddress.value;
206
+ receivers[i].proportion = currentReceiverProportion.value;
207
+ selected.value = currentReceiverAddress.value = currentReceiverProportion.value = "";
208
+ };
209
+ const removeReceiver = (receiver) => {
210
+ const i = receivers.map(x => x.address).indexOf(selected.value);
211
+ receivers.splice(i, 1);
212
+ selected.value = currentReceiverAddress.value = currentReceiverProportion.value = ""
213
+ };
214
+
215
+ // data formatting
216
+ const toBN = (num) => ethers.BigNumber.from(num);
217
+ const getPerSecondFlowRateByDay = (amountPerDay) => {
218
+ return Math.round(
219
+ (Number(amountPerDay) / 86400) * 10 ** 18
220
+ ).toString();
221
+ };
222
+ const getMFAUserData = () => {
223
+ return abiCoder.encode(
224
+ [
225
+ "address",
226
+ "uint256",
227
+ "address[]",
228
+ "uint256[]"
229
+ ],
230
+ [
231
+ mfaData.signerAddress,
232
+ mfaData.ratioPct || "0",
233
+ filteredReceivers.value.map(x => x.address),
234
+ filteredReceivers.value.map(x => x.proportion)
235
+ ]);
236
+ }
237
+
238
+ // text formatting
239
+ const formatBalance = (balance) => Number(ethers.utils.formatEther(toBN(balance || "0"))).toFixed(18);
240
+
241
+ // async
242
+ const getBalanceData = async (signerAddress) => {
243
+ const isNativeAsset = token.nativeTokenSymbol !== "";
244
+ const balanceData = await token.realtimeBalanceOf({
245
+ providerOrSigner: provider,
246
+ account: signerAddress,
247
+ timestamp: blockTimestamp.value || Math.floor(new Date().getTime() / 1000).toString()
248
+ })
249
+
250
+ const underlyingBalance = await provider.getBalance(signerAddress);
251
+ return { superTokenBalanceData: balanceData, underlyingBalance };
252
+ }
253
+ const getFlowData = async (sender, receiver) =>
254
+ ({
255
+ ...await token.getFlow({
256
+ sender,
257
+ receiver,
258
+ providerOrSigner: provider
259
+ }),
260
+ address: receiver
261
+ });
262
+ const getAccountNetFlow = async (account) =>
263
+ await token.getNetFlow({
264
+ account,
265
+ providerOrSigner: provider
266
+ });
267
+ const getFlowAndBalanceData = async (account) => {
268
+ const { superTokenBalanceData } = await getBalanceData(account);
269
+ const flowRate = await getAccountNetFlow(account);
270
+ return {
271
+ availableBalance: superTokenBalanceData.availableBalance,
272
+ deposit: superTokenBalanceData.deposit,
273
+ owedDeposit: superTokenBalanceData.owedDeposit,
274
+ flowRate,
275
+ address: account
276
+ };
277
+ }
278
+ const loadToken = async () => {
279
+ const superToken = await framework.loadSuperToken(currentToken.value);
280
+ token = superToken;
281
+ tokenData.address = superToken.address;
282
+ if (signer.value) {
283
+ const { superTokenBalanceData, underlyingBalance } = await getBalanceData(signer.value._address);
284
+ tokenData.balance = superTokenBalanceData.availableBalance;
285
+ tokenData.underlyingBalance = underlyingBalance;
286
+ }
287
+ tokenData.name = await superToken.symbol({
288
+ providerOrSigner: provider
289
+ });
290
+ tokenData.underlyingName = superToken.nativeTokenSymbol
291
+ || await superToken.underlyingToken.connect(provider).symbol();
292
+ }
293
+ const getAccounts = async () => {
294
+ const ethAccounts = await provider.listAccounts();
295
+ accounts.push(...ethAccounts);
296
+ }
297
+ const getSigners = async () => {
298
+ const signersPromise = accounts.map(x => provider.getSigner(x));
299
+ return await Promise.all(signersPromise);
300
+ }
301
+ const getAndSetSumBalance = async (addresses) => {
302
+ const addressBalances = await Promise.all([...addresses, mfaData.mfaAddress].map(x => getBalanceData(x)));
303
+ const stbds = addressBalances.map(x => x.superTokenBalanceData);
304
+ const abSum = stbds.map(x => x.availableBalance).reduce((a, b) => toBN(a).add(toBN(b)), toBN(0));
305
+ const depSum = stbds.map(x => x.deposit).reduce((a, b) => toBN(a).add(toBN(b)), toBN(0));
306
+ const odSum = stbds.map(x => x.owedDeposit).reduce((a, b) => toBN(a).add(toBN(b)), toBN(0));
307
+
308
+ balanceSum.value = abSum.add(depSum).sub(odSum);
309
+ console.log("BALANCE SUM:", formatBalance(balanceSum.value));
310
+ console.log("AVB SUM (+):", formatBalance(abSum));
311
+ console.log("DEP SUM (+):", formatBalance(depSum));
312
+ console.log("ODE SUM (-):", formatBalance(odSum));
313
+ }
314
+ const impersonateAccount = async () => {
315
+ await provider.send(
316
+ "hardhat_impersonateAccount",
317
+ [mfaData.signerAddress]
318
+ );
319
+ const ethersSigner = await provider.getSigner(mfaData.signerAddress);
320
+ signer.value = ethersSigner;
321
+ passedSigner = ethersSigner;
322
+ }
323
+ const _increaseTime = async (seconds) => {
324
+ await provider.send("evm_increaseTime", [seconds]);
325
+ await provider.send("evm_mine", []);
326
+ }
327
+ const increaseTime = async () => {
328
+ await _increaseTime(Number(increaseTimeSeconds.value));
329
+ await getAndSetCurrentBlockTimestamp();
330
+ await loadToken();
331
+ await setupData();
332
+ await getAndSetSumBalance(accounts.map(x => x));
333
+ }
334
+ const getAndSetCurrentBlockTimestamp = async () => {
335
+ const block = await provider.getBlock();
336
+ blockTimestamp.value = block.timestamp;
337
+ }
338
+ const takeSnapshotAndReturnId = async () => {
339
+ return await provider.send(
340
+ "evm_snapshot",
341
+ []
342
+ );
343
+ }
344
+ const revertToSnapshot = async (snapshotId) => {
345
+ await provider.send(
346
+ "evm_revert",
347
+ [snapshotId]
348
+ );
349
+ return await takeSnapshotAndReturnId();
350
+ }
351
+ const resetState = async () => {
352
+ try {
353
+ const snapshotId = sessionStorage.getItem(RESET_SNAPSHOT_ID);
354
+ const newId = await revertToSnapshot(snapshotId);
355
+ sessionStorage.setItem(RESET_SNAPSHOT_ID, newId);
356
+ await setupData();
357
+ } catch (err) {
358
+ console.error(err);
359
+ }
360
+ }
361
+ const setupData = async () => {
362
+ const senderData = await getFlowAndBalanceData(mfaData.signerAddress);
363
+ const mfaFlowData = await getFlowAndBalanceData(mfaData.mfaAddress);
364
+ const mfaToReceiversData = await Promise.all(
365
+ accounts.map(x => getFlowData(mfaData.mfaAddress, x))
366
+ );
367
+ const mfaReceivers = mfaToReceiversData.filter(x => x.flowRate > 0).map(x => x.address);
368
+ const filteredReceiversData = await Promise.all(mfaReceivers.map(x => getFlowAndBalanceData(x)));
369
+ balanceData.sender = senderData;
370
+ balanceData.mfa = mfaFlowData;
371
+ balanceData.receivers = filteredReceiversData;
372
+
373
+ agreementData.senderToMfa = await getFlowData(mfaData.signerAddress, mfaData.mfaAddress);
374
+ agreementData.mfaToReceivers = await Promise.all(mfaReceivers.map(x => getFlowData(mfaData.mfaAddress, x)));
375
+ receivers.splice(0, receivers.length);
376
+ receivers.push(
377
+ ...filteredReceiversData.map(x => ({ address: x.address, proportion: 1 }))
378
+ );
379
+ }
380
+ /** initialize signer, framework, token */
381
+ const initialize = async () => {
382
+ mfaData.signerAddress = accounts[0];
383
+ await impersonateAccount();
384
+ const sf = await sdkCore.Framework.create({
385
+ chainId: 31337,
386
+ provider: provider,
387
+ resolverAddress: RESOLVER_ADDRESS,
388
+ protocolReleaseVersion: "test",
389
+ });
390
+ framework = sf;
391
+ await getAndSetCurrentBlockTimestamp();
392
+ await loadToken();
393
+ await setupData();
394
+ }
395
+
396
+ // transaction functions
397
+ const upgradeToSuperToken = async (signer) => {
398
+ const ethBalance = await provider.getBalance(signer._address);
399
+ await token.upgrade({ amount: ethers.utils.parseUnits("100") }).exec(signer);
400
+ }
401
+ const _modifyStream = async (action, sender, receiver, flowRate, isMfa) => {
402
+ loading.value = true;
403
+ try {
404
+ console.log("modifying stream:", action);
405
+ if (signer.value == null) {
406
+ await impersonateAccount();
407
+ }
408
+ const s = await provider.getSigner(signer.value._address);
409
+ const userData = isMfa ? getMFAUserData() : "0x";
410
+ const txn = action === "create" ?
411
+ await token.createFlow({
412
+ receiver,
413
+ flowRate: getPerSecondFlowRateByDay(flowRate),
414
+ userData
415
+ }).exec(s)
416
+ : action === "update"
417
+ ? await token.updateFlow({
418
+ receiver,
419
+ flowRate: getPerSecondFlowRateByDay(flowRate),
420
+ userData
421
+ }).exec(s)
422
+ : await token.deleteFlow({
423
+ sender,
424
+ receiver,
425
+ userData
426
+ }).exec(s);
427
+ const receipt = await txn.wait();
428
+
429
+ console.log("RECEIPT", receipt);
430
+ const block = await provider.getBlock(receipt.blockNumber);
431
+ blockTimestamp.value = block.timestamp;
432
+ await setupData();
433
+ await getAndSetSumBalance(accounts.map(x => x));
434
+ } catch (err) {
435
+ console.error(err);
436
+ } finally {
437
+ loading.value = false;
438
+ }
439
+ }
440
+ const senderToMfaModifyStream = async (action) => {
441
+ _modifyStream(action, signer.value._address, mfaData.mfaAddress || MFA_ADDRESS, mfaData.flowRate, true);
442
+ }
443
+ const modifyStream = async (action) => {
444
+ _modifyStream(action, flowData.sender, flowData.receiver, flowData.flowRate, false);
445
+ }
446
+
447
+ // initialization
448
+ getAccounts();
449
+
450
+ return {
451
+ addReceiver,
452
+ formatBalance,
453
+ hasValidMFAInput,
454
+ impersonateAccount,
455
+ increaseTime,
456
+ isAddress,
457
+ loadToken,
458
+ modifyStream,
459
+ removeReceiver,
460
+ resetState,
461
+ senderToMfaModifyStream,
462
+ updateReceiver,
463
+
464
+ accounts,
465
+ agreementData,
466
+ balanceData,
467
+ balanceSum,
468
+ blockTimestamp,
469
+ currentReceiverAddress,
470
+ currentReceiverProportion,
471
+ currentToken,
472
+ filteredReceivers,
473
+ flowData,
474
+ impersonatedSignerAddress,
475
+ increaseTimeSeconds,
476
+ loading,
477
+ mfaData,
478
+ providerNetwork,
479
+ receiverAddresses,
480
+ receivers,
481
+ selected,
482
+ signer,
483
+ signerAddress,
484
+ token,
485
+ tokenData,
486
+ }
487
+ }
488
+ }).mount('#app')
489
+ </script>
490
+ </body>
491
+ <div id="app">
492
+ <h1 class="loading d-flex justify-content-center align-items-center" v-if="loading">loading...</h1>
493
+ <div class="p-3">
494
+ <h2 class="d-flex align-items-center justify-content-center">
495
+ <i class="nes-icon coin is-large"></i>
496
+ <i class="nes-mario"></i>
497
+ Multi Flow Block Explorer
498
+ <i class="nes-mario"></i>
499
+ <i class="nes-icon coin is-large"></i>
500
+ </h2>
501
+ <div>
502
+ <div>
503
+ <div>
504
+ <h4>Global Information</h4>
505
+ <p>
506
+ Balances Sum: {{ formatBalance(balanceSum) }}
507
+ </p>
508
+ <p>
509
+ Current block timestamp: {{ blockTimestamp }}
510
+ </p>
511
+ </div>
512
+ <div>
513
+ <h4>General Information</h4>
514
+ <p>
515
+ Selected Token: {{ tokenData.name }} | {{
516
+ tokenData.address }}
517
+ </p>
518
+ <p>MFA Address: {{ mfaData.mfaAddress }}</p>
519
+ <p>Selected Impersonated Signer: {{ signerAddress }}</p>
520
+ <p>
521
+ Token Balance: {{ formatBalance(tokenData.balance)
522
+ }} {{ tokenData.name }}
523
+ </p>
524
+ <p>
525
+ Underlying Balance: {{
526
+ formatBalance(tokenData.underlyingBalance) }} {{
527
+ tokenData.underlyingName}}
528
+ </p>
529
+ </div>
530
+ <div class="input-table mt-3">
531
+ <div class="input-container">
532
+ <label for="signerAddress">Signer</label>
533
+ <input class="ml-2" type="text" v-model="mfaData.signerAddress" name="signerAddress" />
534
+ <button type="button" class="nes-btn is-primary" @click="impersonateAccount"
535
+ :disabled="!isAddress(mfaData.signerAddress)">
536
+ Impersonate
537
+ </button>
538
+ </div>
539
+ <div class="input-container">
540
+ <label for="mfaAddress">MFA Address</label>
541
+ <input class="ml-2" type="text" v-model="mfaData.mfaAddress" name="mfaAddress" />
542
+ </div>
543
+ <div class="input-container">
544
+ <label for="signerAddress">Token</label>
545
+ <input class="ml-2" type="text" v-model="currentToken" name="currentToken" />
546
+ <button type="button" class="nes-btn is-primary" @click="loadToken">Load Token</button>
547
+ </div>
548
+ <div class="input-container">
549
+ <label for="ratioPct">Ratio Percent</label>
550
+ <input class="ml-2" type="number" v-model="mfaData.ratioPct" name="ratioPct" />
551
+ </div>
552
+ <div class="input-container">
553
+ <label for="flowRate">Flow Rate (/day)</label>
554
+ <input class="ml-2" type="number" v-model="mfaData.flowRate" name="flowRate" />
555
+ </div>
556
+ </div>
557
+ <div class="mt-3">
558
+ <h4>Receivers</h4>
559
+ <select class="mb-3" style="width: 420px" size="5" v-model="selected">
560
+ <option v-for="receiverAddress in receiverAddresses">
561
+ {{receiverAddress}}
562
+ </option>
563
+ </select>
564
+ <div class="input-container">
565
+ <label for="currentReceiverAddress">Receiver Address</label>
566
+ <input class="ml-2" type="text" size="50" v-model="currentReceiverAddress"
567
+ name="currentReceiverAddress" />
568
+ </div>
569
+ <div class="input-container">
570
+ <label for="currentReceiverProportion">Receiver Proportion</label>
571
+ <input class="ml-2" style="width: 69px" type="number" min="0" max="1"
572
+ v-model="currentReceiverProportion" name="currentReceiverProportion" />
573
+ </div>
574
+ <div class="d-flex justify-content-around mt-3 mb-3">
575
+ <button type="button" class="nes-btn is-primary" @click="addReceiver">Add receiver</button>
576
+ <button type="button" class="nes-btn is-primary" @click="updateReceiver" :disabled='selected === ""'>
577
+ Update receiver
578
+ </button>
579
+ <button type="button" class="nes-btn is-primary" @click="removeReceiver" :disabled='selected === ""'>
580
+ Remove receiver
581
+ </button>
582
+ </div>
583
+ </div>
584
+ <div class="d-flex justify-content-around mb-3">
585
+ <button type="button" class="nes-btn is-primary" @click='senderToMfaModifyStream("create")'
586
+ :disabled="hasValidMFAInput() === false">
587
+ Start Stream
588
+ </button>
589
+ <button type="button" class="nes-btn is-primary" @click='senderToMfaModifyStream("update")'
590
+ :disabled="hasValidMFAInput() === false">
591
+ Update Stream
592
+ </button>
593
+ <button type="button" class="nes-btn is-primary" @click='senderToMfaModifyStream("delete")'>
594
+ Delete Stream
595
+ </button>
596
+ </div>
597
+ <button type="button" class="nes-btn is-error" @click="resetState">
598
+ Reset to initial state
599
+ </button>
600
+ <div class="input-container">
601
+ <label for="increaseTimeSeconds">Seconds</label>
602
+ <input class="ml-2" type="text" v-model="increaseTimeSeconds" name="increaseTimeSeconds" />
603
+ <button type="button" class="nes-btn is-primary" @click="increaseTime">
604
+ Increase time
605
+ </button>
606
+ </div>
607
+ </div>
608
+ <div>
609
+ <h4>Accounts</h4>
610
+ <ul>
611
+ <li v-for="account in accounts">{{ account }}</li>
612
+ </ul>
613
+ </div>
614
+ </div>
615
+ <h4>Account State</h4>
616
+ <div class="mfa-flows-container d-flex align-items-center justify-content-around">
617
+ <div class="account-container">
618
+ <b>Sender</b>
619
+ <p>available balance: {{ formatBalance(balanceData.sender.availableBalance) }}</p>
620
+ <p>deposit: {{ formatBalance(balanceData.sender.deposit) }}</p>
621
+ <p>owed deposit: {{ formatBalance(balanceData.sender.owedDeposit) }}</p>
622
+ <p>net flow rate: {{ formatBalance(balanceData.sender.flowRate) }}</p>
623
+ </div>
624
+ <div class="account-container">
625
+ <b>MFA</b>
626
+ <p>available balance: {{ formatBalance(balanceData.mfa.availableBalance) }}</p>
627
+ <p>deposit: {{ formatBalance(balanceData.mfa.deposit) }}</p>
628
+ <p>owed deposit: {{ formatBalance(balanceData.mfa.owedDeposit) }}</p>
629
+ <p>net flow rate: {{ formatBalance(balanceData.mfa.flowRate) }}</p>
630
+ </div>
631
+ <div class="d-flex flex-column">
632
+ <div class="receiver-container" v-for="(receiver, i) in balanceData.receivers">
633
+ <b>Receiver {{ i + 1 }}: {{ receiver.address.substring(0, 6) }}</b>
634
+ <p>available balance: {{ formatBalance(receiver.availableBalance) }}</p>
635
+ <p>deposit: {{ formatBalance(receiver.deposit) }}</p>
636
+ <p>owed deposit: {{ formatBalance(receiver.owedDeposit) }}</p>
637
+ <p>net flow rate: {{ formatBalance(receiver.flowRate) }}</p>
638
+ </div>
639
+ </div>
640
+ </div>
641
+ <h4 class="mt-5">Agreement State</h4>
642
+ <div class="mfa-flow-agreements-container d-flex align-items-center justify-content-around">
643
+ <div class="account-container">
644
+ <b>Sender -> MFA</b>
645
+ <p>deposit: {{ formatBalance(agreementData.senderToMfa.deposit) }}</p>
646
+ <p>owed deposit: {{ formatBalance(agreementData.senderToMfa.owedDeposit) }}</p>
647
+ <p>flow rate: {{ formatBalance(agreementData.senderToMfa.flowRate) }}</p>
648
+ </div>
649
+
650
+ <div class="d-flex flex-column">
651
+ <div class="receiver-container" v-for="(receiver, i) in agreementData.mfaToReceivers">
652
+ <b>MFA -> Receiver {{ i + 1 }}: {{ receiver.address.substring(0, 6) }}</b>
653
+ <p>deposit: {{ formatBalance(receiver.deposit) }}</p>
654
+ <p>owed deposit: {{ formatBalance(receiver.owedDeposit) }}</p>
655
+ <p>net flow rate: {{ formatBalance(receiver.flowRate) }}</p>
656
+ </div>
657
+ </div>
658
+ </div>
659
+
660
+ <div>
661
+ <h4>Arbitrary Stream Modifications</h4>
662
+ <div class="input-container">
663
+ <label for="sender">Sender</label>
664
+ <input class="ml-2" type="string" v-model="flowData.sender" name="sender" />
665
+ </div>
666
+ <div class="input-container">
667
+ <label for="receiver">Receiver</label>
668
+ <input class="ml-2" type="string" v-model="flowData.receiver" name="receiver" />
669
+ </div>
670
+ <div class="input-container">
671
+ <label for="flowData.flowRate">Flow Rate</label>
672
+ <input class="ml-2" type="string" v-model="flowData.flowRate" name="flowData.flowRate" />
673
+ </div>
674
+ <button type="button" class="nes-btn is-primary" @click='modifyStream("create")'>
675
+ Create Stream
676
+ </button>
677
+ <button type="button" class="nes-btn is-primary" @click='modifyStream("update")'>
678
+ Update Stream
679
+ </button>
680
+ <button type="button" class="nes-btn is-primary" @click='modifyStream("delete")'>
681
+ Delete Stream
682
+ </button>
683
+ </div>
684
+ </div>
685
+ </div>
686
+
687
+ </html>